Я хочу иметь возможность настроить обработку структуры на основе присутствия типа в структуре (без написания какого-либо дополнительного кода для пользовательской структуры), например:
struct Normal_t
{
};
struct Custom_t
{
using my_custom_type = bool;
};
Похоже, ядолжен быть в состоянии сделать что-то подобное, но это не сработает:
template <class T, typename Enabler = void>
struct has_custom_type
{
bool operator()() { return false; }
};
template <class T>
struct has_custom_type<T, typename T::my_custom_type>
{
bool operator()() { return true; }
};
bool b_normal = has_custom_type<Normal_t>()(); // returns false
bool b_custom = has_custom_type<Custom_t>()(); // returns false, INCORRECT? should return true?
Чего я не понимаю, так это того, что стандартная библиотека использует нечто подобное, но, по-видимому, более замысловатое для своих черт типа.Например, это работает:
template<bool test, class T = void>
struct my_enable_if
{
};
template<class T>
struct my_enable_if<true, T>
{
using type = T;
};
template <class T, class Enabler = void>
struct foo
{
bool operator()() { return false; }
};
template <class T>
struct foo<T, typename my_enable_if<std::is_integral<T>::value>::type>
{
bool operator()() { return true; }
};
bool foo_float = foo<float>()(); // returns false
bool foo_int = foo<int>()(); // returns true
В обоих случаях специализация происходит на основе присутствия типа в структуре, в одном случае typename T::my_custom_type
, а в другом typename my_enable_if<std::is_integral<T>::value>::type
.Почему работает вторая версия, а не первая?
Я нашел этот обходной путь, используя синтаксис ... пакета параметров, но мне бы очень хотелось понять, есть ли способ сделать это, используя обычныйспециализация шаблона без использования синтаксиса пакета параметров, и если нет, то почему.
template<typename ...Args>
bool has_custom_type_2(Args&& ...args) { return false; }
template<class T, std::size_t = sizeof(T::my_custom_type)>
bool has_custom_type_2(T&) { return true; }
template<class T, std::size_t = sizeof(T::my_custom_type)>
bool has_custom_type_2(T&&) { return true; } /* Need this T&& version to handle has_custom_type_2(SomeClass()) where the parameter is an rvalue */
bool b2_normal = has_custom_type_2(Normal_t()); // returns false
bool b2_custom = has_custom_type_2(Custom_t()); // returns true - CORRECT!