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

标签 c++ c++17 sfinae

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

关于c++ - 如何使用 type_traits 仅在特定类型上添加模板类的成员函数 | C++,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65922386/

相关文章:

c++ - 类型特征以匹配指向集合的指针

c++ - Boost 库不使用 G++ 在 Netbeans 中编译

C++ 重组数组以填补空白?

c++ - 有人可以解释这个模板函数声明语法吗

c++ - 将 std::vector<uint8_t> 转换为 std::string_view

c++ - 如何确保 C++ 类模板中非静态数据成员的正确初始化

macos - 错误 : 'uncaught_exceptions' is unavailable: introduced in macOS 10. 12

c++ - 类模板中的 typedef 引用另一个类模板中的 typedef 的 SFINAE 失败

c++ - 模板运行版本不同于调试

c++ - 消除函数指针和指向类实例的指针之间的歧义