我有一个Foo<T>
我派生的模板类,FooDerived<T>
它又是模板类的模板参数Bar<T>
,即我最终得到类似Bar< FooDerived<T> >
.
template <typename T>
class Foo
{
public:
typedef T type_t;
virtual double compute() { return 1.0; }
};
template <typename T>
class FooDerived : public Foo<T>
{
public:
double compute() { return 42.0; }
};
template <typename T>
class Bar : public T
{
public:
void f()
{
// This function could vary depending on U (and possibly T)
std::cout << "Bar< T<U> > : " << this->compute() << std::endl;
}
};
我正在尝试Bar
基于FooDerived
. 例如,Bar< FooDerived<int> >
并且Bar< FooDerived<float> >
会有不同的行为。
int main(void)
{
Bar< FooDerived<int> > a;
a.f();
Bar< FooDerived<float> > b;
b.f();
}
如何在 C++03(或 C++11)中有效地实现这一点?高效,我的意思是我想避免无用的代码重复(实际程序涉及的类型和函数比这个例子多得多)。此外,使用代码的人应该能够在不需要修改代码的情况下添加他们的专业化,因此任何类型的switch
解决方案都不会被采用。
我一直在寻找类似 SFINAE 的解决方案,boost::mpl
例如检查类型,但似乎没有什么能实现我的目标。我想这可能不适用于那种模板专业化。因为编译器似乎并不认为它是一种专业化,所以我总是以这种方式结束,例如,如果我尝试做这样的事情:boost::mpl::if_
boost::is_same
error: redefinition of 'Bar'
模板类 Bar : public T, private boost::mpl::if_, int, boost::mpl::false_>
使用boost::mpl::if_
,无论是作为私有继承还是额外的模板参数,似乎都无法实现特化。
那么实现这样的事情的正确方法是什么?
更新 1
专门化所有案例是可能的,但隐藏在这个例子背后的真正问题实际上要复杂得多。我有一个CachedFunction<T> : public T
whereT
派生自Function<U>
(函数、可微函数、两次可微函数等) whereU
是存储类型(密集或稀疏矩阵)。CachedFunction
包含大量函数,其实现取决于存储类型和函数类型。因此,元编程似乎是避免某些代码重复的好方法。
更新 2
作为对所提供答案的回应:对于所有涉及的案例,我试图避免这些显式的模板专业化。试着想象有 3 或 4 个派生自 的类Foo
,有 2 或 3 种类型Foo
,并且Bar
包含 6 或 7 个函数,需要根据所Foo
考虑的派生类的类型和派生类进行不同的处理。基本上,对于每个i
,j
和k
,我需要实现:
template<> void Bar<FooDerived_i<Type_j> >::f_k(){ ... }
因此,我试图看看是否有任何其他“更清洁”的方式。
更新 3
如果我使用boost::is_same
,我可以做这样的事情,但是这个解决方案使得在不修改代码的情况下处理新类型变得更加困难。
这是一个例子:
#include <iostream>
#include <boost/type_traits/is_same.hpp>
typedef int type1;
typedef float type2;
template <typename T>
class Foo
{
public:
typedef T type_t;
virtual double compute() { return 1.0; }
};
template <typename T>
class FooDerived
{
public:
typedef T type_t;
double compute() { return 42.0; }
};
template <class T>
class Bar : public T
{
public:
void f()
{
// types have to be known...
if (boost::is_same<typename T::type_t, type1>::value)
std::cout << "Bar< T<type1> > : " << this->compute() << std::endl;
else if (boost::is_same<typename T::type_t, type2>::value)
std::cout << "Bar< T<type2> > : " << this->compute() << std::endl;
}
};
int main(void)
{
Bar< Foo<type1> > a;
a.f();
Bar< FooDerived<type2> > b;
b.f();
}