使用继承 class 中的模板显式特化

Template explicit specialization in class using inheritance

昨天我询问了 class 中的模板显式特化。 Link.

现在我有同样的目的,但现在我想使用继承来避免代码重复。如果我在基 class 中声明一个函数,我不能在派生 class.

中声明此函数的特化

我的代码:

#include <stdexcept>
#include <iostream>

class Base
{
public:
    template <typename T>
    T fun()
    {
        throw std::runtime_error("Unsupported template param");
    }
};

class Derived : public Base
{
};

template <>
bool Base::fun<bool>()
{
    return true;
}

template <>
float Derived::fun<float>()
{
    return 5.6f;
}

template <>
double Derived::fun<double>()
{
    return 5.684;
}

int main()
{
    Derived d;
    bool d_b = d.fun<bool>();
    float d_f = d.fun<float>();
    double d_d = d.fun<double>();
    char d_error = d.fun<char>();
}

VS 代码错误:

use of inherited members is not allowed

g++

error: template id "fun" for "float Derived :: fun ()" does not match any template declaration

英特尔 C++ 编译器:

source/app.cpp:25:16: error: no function template matches function template specialization 'fun'
float Derived::fun<float>()
               ^
source/app.cpp:30:1: error: extraneous 'template<>' in declaration of variable 'fun'
template <>
^~~~~~~~~~~
source/app.cpp:31:17: error: redefinition of 'fun' as different kind of symbol
double Derived::fun<double>()
                ^
source/app.cpp:25:16: note: previous definition is here
float Derived::fun<float>()

如果在C++中不可能,请回答另一个问题:在c++中有什么广为人知的做法来做我想做的。在我使用 D 语言之前,一个人说我不会问自己“为什么”的问题。相反,我只是尝试将 D 方法转移到 C++。我同意。这就是我问的原因。

也许更好的方法是忽略模板并声明单独的函数?例如:

如果您在 Derived 中添加 public fun 的模板定义,这将编译。
但这可能不会做你想要的。 特别是d.fun<bool>();不会执行Base中的实现,而是Derived中的实现。

您不能在派生中专门化模板函数 类。

您也不能在模板函数上使用子类型多态性:模板不能是虚拟的。

您可以使用 CRTP 实现某种类型的静态多态性。

是的,删除模板并使用分离的函数会起作用(a.toX()...)。

另一种选择是使用重载(即传递一个伪参数或目标变量并编写不同的实现)。

根据要求为虚拟参数解决方案添加示例:

namespace TO {
    static const bool BOOL = false;
    static const double DOUBLE = 0.0;
    static const int INT = 0;
}

struct A {
 bool convert(bool dummy) {
     return true;
 }
};

struct B : public A {
    using A::convert; // important

    int convert(int dummy) {
        return 2;
    }

    double convert(double dummy) {
        return 3.0;
    }
};

int main() {
    B b;
    std::cout << b.convert(TO::BOOL) << std::endl;
    std::cout << b.convert(TO::DOUBLE) << std::endl;
    std::cout << b.convert(TO::INT) << std::endl;
}

这种方案在调用函数时存在隐式转换的风险。 toX() 可能是一个更安全的选择。