Я пытаюсь объединить подходы, использованные в этом ответе для определения, имеет ли класс переменную-член x
с этим ответом , чтобы выбрать различные реализации в зависимости от того, что используется enable_if
.
По сути, я хочу написать класс характеристик, который, учитывая тип T
, обеспечивает доступ к члену T::x
, если он существует, и в противном случае предоставляет значение по умолчанию.
Следующий код не компилируется на g ++: ( Проводник компилятора )
#include <iostream>
#include <type_traits>
// classes with / without x member
struct WithX { static constexpr int x = 42; };
struct WithoutX {};
// trait to detect x
template <typename T, typename = void>
struct HasX : std::false_type { };
template <typename T>
struct HasX <T, decltype((void) T::x)> : std::true_type { };
// trait to provide default for x
template <typename T>
struct FooTraits
{
template <bool enable = HasX<T>::value>
static constexpr std::enable_if_t< enable, size_t> x() { return T::x; }
template <bool enable = HasX<T>::value>
static constexpr std::enable_if_t<!enable, size_t> x() { return 1; }
};
int main() {
std::cout << HasX<WithX>::value << std::endl;
// Uncomment the following line to make this compile with g++
//std::cout << HasX<WithoutX>::value << std::endl;
std::cout << FooTraits<WithoutX>::x() << std::endl;
}
g ++ выдает сообщения об ошибках,
error: 'x' is not a member of 'WithoutX'
struct HasX <T, decltype((void) T::x)> : std::true_type { };
в части, которая должна определить, является ли x
членом в первую очередь. Любопытно, что если я раскомментирую вторую и последнюю строку, которая сама создает экземпляр HasX<WithoutX>::value
, g ++ компилируется без ошибок ( Проводник компилятора ).
Компиляция clang и msvc без проблем компилируется в Compiler Explorer.
Что здесь не так?