`std::enable_if` SFINAE 通过模板参数自定义类型?
`std::enable_if` SFINAE custom type via template parameter?
第一个问题:假设我有一个像这样的自定义struct
:
struct Var {};
struct is_var_type: std::integral_constant<bool, std::is_same<Var, typename std::remove_cv<T>::type>::value> {};
在此之后,我想使用 std::enable_if
通过模板参数 SFINAE 获得一些自定义类型,但我无法弄清楚。我只能这样做:
template<typename T>
void variant(T a)
{
if (is_var_type<Var>::value){
std::cout << " " << true;
}
else {
std::cout << " " << false;
}
}
我想做这样的东西,但是std::is_integral
已经定义好了。定制款是如何制作的?
template<class T, typename std::enable_if<std::is_integral<T>::value>::type* = nullptr> // I couldn't figure out how to make custom integral_constant via template parameter
T foo3(T t) // note, function signature is unmodified
{
return t; //so this type should be an int, but I want to make sure that this type T is is_var_type struct, is this possible?
}
第二个问题:如果我们像这样添加一些容器类型,这种方式是否可行?
struct Var {};
struct ListVar: public std::list<Var>
struct is_var_type: std::integral_constant<bool, std::is_same<ListVar, typename std::remove_cv<T>::type>::value> {};
– 但我遇到了一个更令人困惑的编译时错误,比如 cannot deduce multiple type in gcc 4.9
.
我会让 is_var_type
成为模板别名包装 std::is_same
。解决方案可能如下所示。
#include <type_traits> // for std::decay
#include <iostream>
struct Var {};
// define is_var_type
template<class T>
using is_var_type = std::is_same<Var, typename std::decay<T>::type >;
// function that works for Var
template<class T
, typename std::enable_if<is_var_type<T>::value>::type* = nullptr
>
T foo3(T t)
{
std::cout << " T is type Var " << std::endl;
return t;
}
// function that works for int
template<class T
, typename std::enable_if<std::is_same<T,int>::value>::type* = nullptr
>
T foo3(T t)
{
std::cout << " T is type int " << std::endl;
return t;
}
int main()
{
Var v;
foo3(v); // calls foo3 for type Var
int i;
foo3(i); // calls foo3 for type int
return 0;
}
您还可以像在示例中那样使用 std::integral_constant
定义 is_var_type
(您在定义之前缺少 template<class T>
):
template<class T>
struct is_var_type:std::integral_constant<bool,std::is_same<Var,typename std::decay<T>::type>::value >
{
};
编辑:
对于Var
的容器和上面一样,现在我们只检查T
是否是ListVar
类型:
// define structure that is a list of Var
struct ListVar : public std::list<Var>
{
};
// struct that checks whether T is a ListVar
template<class T>
struct is_list_of_var_type : std::integral_constant<bool,std::is_same<ListVar, typename std::remove_cv<T>::type>::value > {};
// function that only works for ListVar
template<class T
, typename std::enable_if<is_list_of_var_type<T>::value>::type* = nullptr
>
T foo3(T t)
{
std::cout << " T is type ListVar " << std::endl;
return t;
}
// ... some code ...
ListVar lv;
foo3(lv); // call foo3 for ListVar
第一个问题:假设我有一个像这样的自定义struct
:
struct Var {};
struct is_var_type: std::integral_constant<bool, std::is_same<Var, typename std::remove_cv<T>::type>::value> {};
在此之后,我想使用 std::enable_if
通过模板参数 SFINAE 获得一些自定义类型,但我无法弄清楚。我只能这样做:
template<typename T>
void variant(T a)
{
if (is_var_type<Var>::value){
std::cout << " " << true;
}
else {
std::cout << " " << false;
}
}
我想做这样的东西,但是std::is_integral
已经定义好了。定制款是如何制作的?
template<class T, typename std::enable_if<std::is_integral<T>::value>::type* = nullptr> // I couldn't figure out how to make custom integral_constant via template parameter
T foo3(T t) // note, function signature is unmodified
{
return t; //so this type should be an int, but I want to make sure that this type T is is_var_type struct, is this possible?
}
第二个问题:如果我们像这样添加一些容器类型,这种方式是否可行?
struct Var {};
struct ListVar: public std::list<Var>
struct is_var_type: std::integral_constant<bool, std::is_same<ListVar, typename std::remove_cv<T>::type>::value> {};
– 但我遇到了一个更令人困惑的编译时错误,比如 cannot deduce multiple type in gcc 4.9
.
我会让 is_var_type
成为模板别名包装 std::is_same
。解决方案可能如下所示。
#include <type_traits> // for std::decay
#include <iostream>
struct Var {};
// define is_var_type
template<class T>
using is_var_type = std::is_same<Var, typename std::decay<T>::type >;
// function that works for Var
template<class T
, typename std::enable_if<is_var_type<T>::value>::type* = nullptr
>
T foo3(T t)
{
std::cout << " T is type Var " << std::endl;
return t;
}
// function that works for int
template<class T
, typename std::enable_if<std::is_same<T,int>::value>::type* = nullptr
>
T foo3(T t)
{
std::cout << " T is type int " << std::endl;
return t;
}
int main()
{
Var v;
foo3(v); // calls foo3 for type Var
int i;
foo3(i); // calls foo3 for type int
return 0;
}
您还可以像在示例中那样使用 std::integral_constant
定义 is_var_type
(您在定义之前缺少 template<class T>
):
template<class T>
struct is_var_type:std::integral_constant<bool,std::is_same<Var,typename std::decay<T>::type>::value >
{
};
编辑:
对于Var
的容器和上面一样,现在我们只检查T
是否是ListVar
类型:
// define structure that is a list of Var
struct ListVar : public std::list<Var>
{
};
// struct that checks whether T is a ListVar
template<class T>
struct is_list_of_var_type : std::integral_constant<bool,std::is_same<ListVar, typename std::remove_cv<T>::type>::value > {};
// function that only works for ListVar
template<class T
, typename std::enable_if<is_list_of_var_type<T>::value>::type* = nullptr
>
T foo3(T t)
{
std::cout << " T is type ListVar " << std::endl;
return t;
}
// ... some code ...
ListVar lv;
foo3(lv); // call foo3 for ListVar