c++ 如何使“enable_if”成为硬要求

ktecyv1j  于 2022-12-01  发布在  其他
关注(0)|答案(3)|浏览(152)

This answer包含以下代码:

#include <type_traits>

template<
    typename T, //real type
    typename = typename std::enable_if<std::is_arithmetic<T>::value, T>::type
> struct S{};

int main() {
   S<int> s; //compiles
   S<char*> s; //doesn't compile
}

然而,通过为模板S指定任意的第二个类型参数,例如S<char*, void>T满足is_arithmetic的要求可以很容易地被击败。有没有办法排除这种可能性?

j1dl9f46

j1dl9f461#

T满足is_arithmetic的要求很容易被推翻
我的意思是,它是SFINAE,又名替换不是一个错误.如果你想在模板中强制特定的类型,你可以使用c20中的概念,或者在c17-c++11中,你有static_assert

template<
    typename T //real type
> struct S{
    static_assert(std::is_arithmetic_v<T>, "T must be arithmetic");
};

没有什么能打败它。

2wnc66cl

2wnc66cl2#

使用概念会容易得多(既然你已经提到过),

template <typename T>
concept Arithmetic = std::is_arithmetic_v<T>;

template<Arithmetic T> struct S{};

Demo

omtl5h9j

omtl5h9j3#

有没有办法排除这种可能性?
是的,有如下所示。特别是,我们可以使第二个参数成为非类型参数,并使用默认值。

template<
    typename T,
    //make the second parameter a non-type parameter with default 
    typename std::enable_if<std::is_arithmetic<T>::value, nullptr_t>::type N = nullptr 
> struct S{};

int main() {
   S<int> s; //compiles 
    //S<int, void> S2;  //DOESN'T COMPILE 
   //S<int, 1> S3;     //DOESN'T COMPILE
   
}

相关问题