如何使用type_traits | c++在特定类型上添加模板类的成员函数


template <typename T>
class A
{
template <std::enable_if_t<std::is_signed_v<T>, bool> = true>
constexpr value_type determinant()
{

}
}

我想要行列式函数只有在类型T是有符号类型时才实例化所以我尝试这个代码,但当类型T是无符号编译器仍然尝试实例化行列式函数。

我不想对每个有符号类型T特化模板函数
我想使用std::is_signed_v类型特征来简化代码

使用SFINAE,当测试的条件与方法本身的模板参数相关时,您可以启用/禁用类的方法。不能测试类的模板形参

可以通过一个方法模板形参来解决这个问题,该方法模板形参默认为类/结构模板形参的类型。

例如

#include <iostream>
#include <type_traits>
template <typename T>
struct foo
{
template <typename U = T,
std::enable_if_t<std::is_signed_v<U>, bool> = true>
constexpr std::size_t bar ()
{ return sizeof(T); }
};
int main() 
{
foo<signed int>   fs;
foo<unsigned int> fu;
fs.bar(); // compile
//fu.bar(); // compilation error
}

这个解决方案的问题是你可以"劫持"。它解释了一个模板参数

fu.bar(); // compilation error
fu.bar<int>(); // compile 

为了避免劫持风险,您可以(其他解决方案是可能的,但这是我的首选)在U

之前添加一个非类型可变模板参数。
// .......VVVVVVVV  add this to avoid the hijacking problem
template <int ...,
typename U = T,
std::enable_if_t<std::is_signed_v<U>, bool> = true>
constexpr std::size_t bar ()
{ return sizeof(T); }
// ...
fu.bar(); // compilation error
fu.bar<int>(); // compilation error
fu.bar<1, 2, 3, int>(); // compilation error

相关内容

  • 没有找到相关文章

最新更新