我正在尝试学习SFINAE。但是,我看到的所有例子都太复杂了,而取得的成就却微不足道。我发现的最有意义的SFINAE是这个:
template<typename T>
class is_class {
typedef char yes[1];
typedef char no [2];
template<typename C>
static yes& test(int C::*); // selected if C is a class type
template<typename C>
static no& test(...); // selected otherwise
public:
static bool const value = sizeof(test<T>(0)) == sizeof(yes);
};
但是,所有文档都专注于编写没有任何main
功能的模板。因此,我不知道如何在main
函数中使用它们,该函数在编译时不会失败。
PS。让我们忘记std::is_class
(如果有任何巨魔评论)。
答案 0 :(得分:2)
您可以这样使用它:
template <typename T>
std::enable_if_t<is_class<T>::value>
foo(const T&)
{
std::cout << "is a class\n";
}
template <typename T>
std::enable_if_t<!is_class<T>::value>
foo(const T&)
{
std::cout << "is not a class\n";
}
,然后在main
中:
int main()
{
std::string s;
int i = 42;
foo(s); // a class
foo(i); // not a class
}
在函数上使用SFINAE的常规方法是:
template <typename T, std::enable_if_t<some_trait<T>::value, int> = 0>
void foo(const T&);
template <typename T>
std::enable_if_t<some_trait<T>::value> foo(const T&);
template <typename T>
void foo(const T&, std::enable_if_t<some_trait<T>::value, int> = 0);
您也可以将SFINAE与“表达式”一起使用
template <typename T>
auto foo(const T& t) -> decltype (bar(t)); // Only available if `bar(t)` exists.
答案 1 :(得分:0)
想象一下,您有一个(相当无用的)函数,以字节为单位返回传递的参数的大小,但是您希望该函数仅可用于类(出于某些不同的奇怪原因)。 SFINAE类的用法:
template<typename T>
class is_class {
typedef char yes[1];
typedef char no [2];
template<typename C>
static yes& test(int C::*); // selected if C is a class type
template<typename C>
static no& test(...); // selected otherwise
public:
static bool const value = sizeof(test<T>(0)) == sizeof(yes);
};
可以是:
template <typename T, typename = std::enable_if_t<is_class<T>::value>>
auto get_class_size(T t) {
return sizeof(T);
};
然后在main()
中:
int main() {
std::vector<int> some_vec;
int some_int;
std::cout << get_class_size(some_vec) << '\n';
//std::cout << get_class_size(some_int) << '\n'; // will result in
// compilation error
}