C++ 继承成员函数的模板专门化
我们想专门化基类的成员函数。但是,它不编译。有人知道有什么替代方案可以编译吗 这里有一个例子C++ 继承成员函数的模板专门化,c++,templates,C++,Templates,我们想专门化基类的成员函数。但是,它不编译。有人知道有什么替代方案可以编译吗 这里有一个例子 struct Base { template<typename T> void Foo() { throw "Foo() is not defined for this type"; } }; struct Derived : public Base { template<> void Foo<int>
struct Base
{
template<typename T>
void Foo()
{
throw "Foo() is not defined for this type";
}
};
struct Derived : public Base
{
template<>
void Foo<int>() { cout << "Foo<int>()" << endl; } // compile error (cannot specialize members from a base class)
template<>
void Foo<double>() { cout << "Foo<double>()" << endl; } // compile error (cannot specialize members from a base class)
};
struct Base
{
模板
void Foo()
{
抛出“未为此类型定义Foo()”;
}
};
结构派生:公共基
{
模板
void Foo(){cout这将编译,除了调用Foo()
:
最终,我们使用重载解决了这个问题
下面是基类的外观
struct Base
{
template<typename T>
class OfType {}
template<typename T>
void Foo(OfType<T>) { static_assert(false, "Foo is not implemented for this type. Please look in the compiler error for more details."); }
};
struct Derived : public Base
{
using Base::Foo;
void Foo(OfType<int>) { // here comes logic for ints }
void Foo(OfType<double>) { // here comes logic for doubles }
};
针对与Alex的讨论(参见John Dibling回答的评论),我的意思是(SSCCE):
#包括
使用名称空间std;
结构基
{
模板
void Foo()
{
//静态_断言(false,“未为此类型定义Foo());
抛出“未为此类型定义Foo()”;
}
};
//您可以在Base中添加任意数量的专门化
模板
void Base::Foo(){是否将不会有多态行为返回到基,并且您无法使模板函数虚拟。不确定您试图实现什么。我们正在尝试创建具有专用成员的工厂类,并且我们希望在不知道如何处理方法未专用的类型时引发异常。我们希望在我们的示例中,h可以创建许多类似于派生类的类。否则,我们就不会有基类。与其在运行时抛出异常,不如在编译时失败。派生的.Foo不会抛出。它只是不编译(链接错误)。此外,我们将无法使用包含更多专门化的DerivedMore扩展派生类。还有其他想法吗?@Alex:您可以简单地为Derived::Foo
:return Base::Foo()添加默认实现
@DyP:我们可以,但这意味着我们必须在每个派生类型中添加它。如果我有很多这样的派生类型会怎么样?@Alex:我不太明白。如果你的派生类有专门的工厂方法,那么你在每个派生类型中都已经有了Foo
函数。如果派生类型没有添加专门化,你甚至没有o提供Foo
方法(从基类继承)@DyP:这就是我想要的。但是正如我所说的,上面的示例没有编译。为了编译,我们需要在每个派生类型中重新实现默认的Foo。但是为什么要抛出它呢?如果它只是不编译就更好了。你是对的。我会将其更改为静态断言,或者将其全部删除。无论如何,上面的加载允许我创建派生类的层次结构。专门化不允许我这样做。顺便说一句,编译器错误比链接错误更好,它会告诉您在代码中的何处使用坏重载,而不仅仅是它不存在(您知道).main返回int not void,当您抛出异常时,抛出从std::exception派生的异常。您不能使用多态性从基调用专用方法,那么重点是什么?
template<typename T>
void Derived::Foo() { cout << "generic" << endl; }
struct Base
{
template<typename T>
class OfType {}
template<typename T>
void Foo(OfType<T>) { static_assert(false, "Foo is not implemented for this type. Please look in the compiler error for more details."); }
};
struct Derived : public Base
{
using Base::Foo;
void Foo(OfType<int>) { // here comes logic for ints }
void Foo(OfType<double>) { // here comes logic for doubles }
};
template<typename S>
class ClassThatUsesFoo
{
private: S s;
template<typename T>
void Bar(T item)
{
s.Foo(Base::OfType<T>()); // this is the code that uses Foo
DoSomeStuffWithItem(item);
}
};
void main()
{
ClassThatUsesFoo<Derived> baz;
baz.Bar(12); // this will internally use Foo for ints
baz.Bar(12.0); // this will use Foo for doubles
baz.Bar("hello world"); // this will give a verbose compile error
}
#include <iostream>
using namespace std;
struct Base
{
template<typename T>
void Foo()
{
//static_assert(false, "Foo() is not defined for this type");
throw "Foo() is not defined for this type";
}
};
// you can add as many specializations in Base as you like
template <>
void Base::Foo<char>() { cout << "Base::Foo<char>()" << endl; }
struct Derived : public Base
{
// just provide a default implementation of Derived::Foo
// that redirects the call to the hidden Base::Foo
template < typename T >
void Foo()
{ Base::Foo<T>(); }
};
// the specializations for Derived
template<>
void Derived::Foo<int>() { cout << "Foo<int>()" << endl; }
template<>
void Derived::Foo<double>() { cout << "Foo<double>()" << endl; }
struct Derived_wo_specialization : public Base
{
/* nothing */
};
int main()
{
Derived d;
d.Foo<char>();
d.Foo<double>();
Derived_wo_specialization dws;
dws.Foo<char>();
dws.Foo<double>();
}