c++ - 基于模板参数的模板参数的类特化

标签 c++ templates boost sfinae specialization

我有一个模板类 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 -like 解决方案将不适用。

我一直在研究涉及 boost::mpl 的类似 SFINAE 的解决方案,例如boost::mpl::if_boost::is_same检查类型,但似乎没有达到我的目标。我想这可能不适用于那种模板特化。我总是以error: redefinition of 'Bar'结尾因为编译器似乎并不认为它是一种特化,例如,如果我尝试做这样的事情:

模板 Bar 类:公共(public) T,私有(private) boost::mpl::if_,int,boost::mpl::false_>

使用 boost::mpl::if_ ,无论是作为私有(private)继承还是额外的模板参数,似乎都无法实现特化。

那么实现这样的目标的正确方法是什么?

更新 1

专门化所有案例是可能的,但隐藏在这个例子背后的真正问题实际上要复杂得多。我有一个 CachedFunction<T> : public T其中 T源自 Function<U> (函数、可微函数、二次可微函数等)其中 U是一种存储类型(密集或稀疏矩阵)。 CachedFunction包含大量函数,其实现取决于存储类型和函数类型。因此,元编程似乎是避免某些代码重复的好方法。

更新 2

针对所提供的答案:我正在努力避免对所有涉及的情况进行这些明确的模板特化。试着想象有 3 或 4 个派生自 Foo 的类, Foo 有 2 种或 3 种类型,那Bar包含 6 或 7 个函数,需要根据 Foo 的类型进行不同处理和派生类考虑。基本上,对于每个 i , jk ,我需要实现:

template<> void Bar<FooDerived_i<Type_j> >::f_k(){ ... }

因此,我想看看有没有其他“更干净”的方法。

更新 3

如果我使用 boost::is_same ,我可以做这样的事情,但这种解决方案使得在不修改代码的情况下处理新类型变得更加困难。

这是一个 example :

#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();
}

最佳答案

(注意,这回答了问题的第一个版本 如果您认为应该删除它,请通过评论告诉我)

你可以这样做:

template <typename T>
class Bar : public T
{
    public:
        std::string name();
};

template<>
std::string Bar<FooDerived<int> >::name() {
  return std::string("int");
  }

template<>
std::string Bar<FooDerived<float> >::name() {
  return std::string("float");
  }

在这里测试:http://coliru.stacked-crooked.com/view?id=9054d3356f438b31b1adbb595620d838-ad7854d9cfd7979d567ca413f0830b65

感谢jogojapan的宝贵建议!

关于c++ - 基于模板参数的模板参数的类特化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17358565/

相关文章:

c++ - 使用挂起的协程进行适当的清理

c++ - 从键盘输入数据时,C++中用户按下 "enter"如何完成输入?

c++ - 用 std::tr1::bind 替换 boost::bind 时出现问题

c++ - boost 测试 - 其他文件中的每个套件

c++ - 具有可变参数的元组内容的部分特化

c++ - 具有递归继承和使用声明的可变参数模板

c++ - 以多模板类中的模板为条件

c++ - 如何导致 std::mktime 失败?

c++ - 关于类模板部分特化和类成员特化的一些混淆

c++ - Windows 资源管理器打开文件夹还原