Как использовать Enable_If для включения функций-членов на основе параметра шаблона класса
-
08-10-2019 - |
Вопрос
В коде:
template<class T>
struct is_builtin
{
enum {value = 0};
};
template<>
struct is_builtin<char>
{
enum {value = 1};
};
template<>
struct is_builtin<int>
{
enum {value = 1};
};
template<>
struct is_builtin<double>
{
enum {value = 1};
};
template<class T>
struct My
{
typename enable_if<is_builtin<T>::value,void>::type f(T arg)
{
std::cout << "Built-in as a param.\n";
}
typename enable_if<!is_builtin<T>::value,void>::type f(T arg)
{
std::cout << "Non - built-in as a param.\n";
}
};
struct A
{
};
int main()
{
A a;
My<int> m;
My<A> ma;
m.f(1);
ma.f(a);
return 0;
}
Я получаю ошибку:
error C2039: 'type' : is not a member of 'std::tr1::enable_if<_Test,_Type>'
Очевидно, я не понимаю, как использовать enable_if
. Отказ То, что я думал, что я могу включить одну или вторую функцию элемента из набора функций участника во время компиляции, но он не работает. Может ли кто-нибудь, пожалуйста, объясните мне, как это сделать правильно?
Отредактировано
Что я действительно не могу понять, почему нет typedef
в одном из этих детей. Компилятор не может найти его, и это не скомпилирует его.
Решение
Вы не можете использовать параметры шаблона класса, чтобы получить Sfinae для функций-членов.
Вам либо нужно
Сделайте функцию элемента шаблоном функции члена и использовать
enable_if
на параметрах шаблона шаблона функции участника илиПереместить функцию участника
f
в класс политики и специализируйтесь на шаблон класса, используяenable_if
.
Другие советы
Вы можете исправить свой код, используя модифицированный enable_if
template < typename T >
struct __Conflict {};
template <bool B, class T = void>
struct __enable_if { typedef __Conflict<T> type; };
template <class T>
struct __enable_if<true, T> { typedef T type; };
Пример использования:
template <typename T>
class Lazy
{
public:
void _ctor(bool b);
void _ctor(typename __enable_if<!std::is_same<T, bool>::value, T>::type);
};
template <typename T>
void Lazy<T>::_ctor(bool b)
{
std::cout << "bool " << b << std::endl;
};
template <typename T>
void Lazy<T>::_ctor(typename __enable_if<!std::is_same<T, bool>::value, T>::type t)
{
std::cout << "T " << t << std::endl;
};
int main(int argc, char **argv)
{
Lazy<int> i;
i._ctor(10);
i._ctor(true);
Lazy<bool> b;
b._ctor(true);
return 0;
}
Вот как это работает (обратите внимание, что для удобства я заменил ваш is_builtin
честь std::is_arithmetic
и используется дальше C ++ 11 вещей, но это работает в любом случае):
template<class T>
struct My
{
template<typename T_ = T, std::enable_if_t<std::is_arithmetic<T_>::value>* = nullptr>
void f(T_ arg)
{
std::cout << "Built-in as a param.\n";
}
template<typename T_ = T, std::enable_if_t<!std::is_arithmetic<T_>::value>* = nullptr>
void f(T_ arg)
{
std::cout << "Non - built-in as a param.\n";
}
};
Решающая часть - привести параметр шаблона в непосредственный контекст Используя параметр шаблона функции по умолчанию T_
что равен параметру шаблона класса T
. Отказ Для более подробной информации см. этот вопрос.
enable_if ожидает метафафункции. Чтобы использовать Bool, вам нужно Enable_if_c. Я удивлен, что вы не получите ошибки, объясняющие эту проблему.
Вы можете зафиксировать вашу метафонцию, объявив типичный файл «Тип» внутри, который просто сам. Тогда вы можете использовать boost::enable_if<is_builtin<T>>::type