使用继承 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++。我同意。这就是我问的原因。
也许更好的方法是忽略模板并声明单独的函数?例如:
- funToBool()
- funToFloat()
- funToDouble()
如果您在 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() 可能是一个更安全的选择。
昨天我询问了 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++。我同意。这就是我问的原因。
也许更好的方法是忽略模板并声明单独的函数?例如:
- funToBool()
- funToFloat()
- funToDouble()
如果您在 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() 可能是一个更安全的选择。