I'm currently wrestling with Visual Studio 2017 (compiling using /std:c++latest
if that's any help).
The code in question simply selects a struct specialization based on the result of some templated constexpr
function. GCC and clang have no trouble compiling it.
Here's my MCVE:
#include <type_traits>
struct A {
enum {
test_trait = true
};
};
template<typename T>
constexpr int choose() {
return T::test_trait;
}
template<typename T, typename Enable=void>
struct Chosen;
template<typename T>
struct Chosen<T, std::enable_if_t<choose<T>() == 1>> {};
void foo() {
// This works
constexpr int chosen = choose<A>();
static_assert(chosen == 1, "");
// This resolves to the undefined struct.
using Chosen_t = Chosen<A>;
Chosen_t x;
(void)x;
}
choose()
is actually a fair bit more complex in my codebase, but the static_assert
still compiles, and checks fine.
I kinda assumed that if the static_assert
compiles, there is no reason for the enable_if
to not be able to do its magic. Am I wrong? I guess "maybe" T
is not technically a dependant type of the enable_if
... But if that was the case, I'd expect GCC and clang to slap my wrist.
I can get around this by wrapping the result of choose()
in a std::integral_constant
, like so:
template<typename T>
struct Chooser : public std::integral_constant<int, choose<T>()> {};
template<typename T>
struct Chosen<T, std::enable_if_t<Chooser<T>::value>> {};
But I'd really rather not have to jump through that hoop.
Should template resolution be able to resolve this the way I expect? I'm worried that the code is actually wrong, and GCC and clang are just being lenient on me.
Code still appears to be broken in MSVC 19.00.23506. However, it appears to work with just one more level of indirection (perhaps a better workaround):
template<typename T, bool>
struct ChosenImpl;
template<typename T>
struct ChosenImpl<T, true> {};
template<typename T>
using Chosen = ChosenImpl<T, choose<T>()>;
Demo
A benefit to this is that we are hiding the second template argument from the caller, which they don't care about anyway.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With