Template-specialization 用于 C++ 中的多个模板之一

Template-specialization for one out of multiple templates in C++

header mycomputationclass.h:

#pragma once
template<typename numberType, bool increaseByOne>
class MyComputationClass
{
   numberType a = 1;
   numberType b = 2;
   numberType compute();
};

#include mycomputationclass.hpp

header实现文件mycomputationclass.hpp:

#pragma once
#include mycomputationclass.h

template<typename numberType, bool increaseByOne>
numberType MyComputationClass<numberType, increaseByOne>::compute()
{
   return a + b;
}
template<typename numberType>
numberType MyComputationClass<numberType, true>::compute()
{
   return a + b + static_cast<numberType>(1);
}

错误:

 error: invalid use of incomplete type ‘class MyComputationClass<numberType, true>’
 numberType MyComputationClass<numberType, true>::compute()
                                                          ^

我找到的所有与专业化相关的主题都只使用一个模板。有人可以帮我吗?

首先请看Why can templates only be implemented in the header file?。现在,您的问题并非源于上述,但是您应该认真考虑是否确实要在 cpp 文件中实现模板。我怀疑你没有。

无论如何,您问的问题是您正在尝试定义一种您尚未专门化的专门化 class 模板的方法。

这里有几个选项。

  • 可以特化class模板,重复全身

    template<typename numberType>
    class MyComputationClass<numberType, true>
    {
       numberType a = 1;
       numberType b = 2;
       numberType compute();
    };
    
  • 您可以使用所有通用代码创建基本 class 模板,并派生 classes 模板,其中仅包含您需要专门化的部分

  • 在 C++17 中你可以使用 if constexpr:

    template<typename numberType, bool increaseByOne>
    numberType MyComputationClass<numberType, increaseByOne>::compute()
    {
        if constexpr (increateByOne)
            return a + b + 1;
        else
            return a + b;
    }
    
  • 在 C++20 中你可以使用 requires 子句:

    template<typename numberType, bool increaseByOne>
    class MyComputationClass
    {
       numberType a = 1;
       numberType b = 2;
       numberType compute() requires increaseByOne
       {
           return a + b + 1;
       };
        numberType compute() requires (!increaseByOne)
       {
           return a + b;
       };
    };
    
  • 在旧的 C++ 中,您可以使用简单的 if。由于 increaseByOne 在编译时已知,编译器会将其优化为 if constexpr。唯一的问题是,如果您在每个分支上返回了不同的类型,或者某些代码在其中一个分支上无效。如此简单 if 是这里的解决方案:

    template<typename numberType, bool increaseByOne>
    numberType MyComputationClass<numberType, increaseByOne>::compute()
    {
        if (increateByOne)
            return a + b + 1;
        else
            return a + b;
    }