В настоящее время я борюсь с Visual Studio 2017 (компиляция с использованием /std:c++latest
, если это поможет).
Рассматриваемый код просто выбирает специализацию структуры на основе результата некоторой шаблонной функции constexpr
. GCC и clang без труда компилируют его.
Вот мой 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()
на самом деле немного сложнее в моей кодовой базе, но static_assert
все еще компилируется и проверяет нормально.
Я вроде бы предположил, что если static_assert
компилируется, то нет никаких оснований для enable_if
быть неспособным сделать свою магию. Я ошибаюсь? Я предполагаю, что «возможно» T
технически не является зависимым типом enable_if
... Но если бы это было так, я бы ожидал, что GCC и лязг ударит меня по запястью.
Я могу обойти это, обернув результат choose()
в std::integral_constant
, примерно так:
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>> {};
Но я бы действительно не хотел прыгать через этот обруч.
Должно ли разрешение шаблонов разрешать это так, как я ожидаю? Я беспокоюсь, что код на самом деле неверен, и GCC и Clang просто снисходительны ко мне.