如何使用这个is_class SFINAE?
How to use this is_class SFINAE?
我正在努力学习 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
(以防任何巨魔评论)。
假设您有一个(相当无用的)函数,该函数 returns 传递的参数的大小(以字节为单位),但您希望该函数仅可用于 classes(对于某些不同的,奇怪的原因)。你的 SFINAE 的使用 class:
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
}
你可能会这样使用它:
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&);
作为return类型:
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.
我正在努力学习 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
(以防任何巨魔评论)。
假设您有一个(相当无用的)函数,该函数 returns 传递的参数的大小(以字节为单位),但您希望该函数仅可用于 classes(对于某些不同的,奇怪的原因)。你的 SFINAE 的使用 class:
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
}
你可能会这样使用它:
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&);
作为return类型:
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.