代码之家  ›  专栏  ›  技术社区  ›  McFlurriez

在标头外编译C++非类型模板参数?

  •  1
  • McFlurriez  · 技术社区  · 2 年前

    这可能是一个愚蠢的问题,但我一直在努力解决这个问题,而ChatGPT解决方案无法解决它。

    我有以下类定义:

    template<typename U, typename = std::enable_if_t<std::is_base_of_v<int, U>>>
    class TestClass {
      public:
        auto print() -> void;
    };
    

    如果我在声明/头本身中实现print(),这是微不足道的:

    template<typename U, std::enable_if_t<std::is_base_of_v<U, int>, int> = 0>
    class TestClass
    {
        auto print()
        {
           std::cout << "Hello";
        }
    };
    

    然而,如果我试图将其移动到用于实现的cpp文件中,则无法对其进行编译。以下是我的一个尝试:

    template<typename U, typename>
    void TestClass<U, std::enable_if_t<std::is_base_of_v<int, U>>>::print()
    {
        std::cout << "Printing from TestClass" << std::endl;
    }
    

    这是该尝试的编译错误:

    main.cpp:14:19: error: template argument for non-type template parameter must be an expression
    void TestClass<U, std::enable_if_t<std::is_base_of_v<int, U>>>::print()
                      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    main.cpp:6:71: note: template parameter is declared here
    template<typename U, std::enable_if_t<std::is_base_of_v<U, int>, int> = 0>
                                                                          ^
    1 error generated.
    

    将其移动到cpp文件中时,正确的语法是什么?

    1 回复  |  直到 2 年前
        1
  •  4
  •   user12002570    2 年前

    常见的方法( 语法方面 )是在定义/声明的第一次出现时指定默认参数,然后在下一次出现时提交,如下所示。

    这意味着 解决这个问题的两种方法 这取决于您在使用问题中给出的两个代码片段中的哪一个。

    方法1

    //specify default argument here
    template<typename U, typename = std::enable_if_t<std::is_base_of_v<int, U>>>
    class TestClass {
      public:
        auto print() -> void;
    };
    //no default argument here
    template<typename U, typename N>
    void TestClass<U, N>::print() 
    {
           std::cout << "Hello"; 
    }
    

    working demo

    方法2

    //specify the default argument here
    template<typename U, std::enable_if_t<std::is_base_of_v<U, int>, int> = 0>
    class TestClass
    {
        auto print() -> void;
        
    };
    //no need to specify default argument here
    template<typename U, std::enable_if_t<std::is_base_of_v<U, int>, int> N>
    void TestClass<U, N>::print()
    {
           std::cout << "Hello";
    }
    

    Working demo