【问题标题】:C++ template partial specialization with inheritance带有继承的 C++ 模板部分特化
【发布时间】:2014-12-12 23:00:16
【问题描述】:

我需要struct 的部分专业化,但我还想使用一些常用功能。例如,假设我有下一个类型:

template <typename A, typename B>
struct Foo  
{
    Foo& func0() { /* common actions with A and B */; return *this; }  
    void func1() { /* common actions with A and B */ }
    void func2() { /* common actions with A and B */ }
}

然后我想将它专门用于模板参数之一 - 例如,我想考虑 Bint 时的特殊情况,并且我想保留 func0func1 的行为与常见的Foo(或者当然,func0() 必须返回我的专业Foo&amp;int),func2 我想重写(假设我对整数有更有效的实现),我还想添加@ 987654333@ 仅供我专业的Foo使用。

当然,我可以简单地写如下:

template <typename A>
struct Foo<A, int>  
{
    Foo& func0() { /* common actions with A and B */; return *this; }  
    void func1() { /* common actions with A and B */ }
    void func2() { /* actions with A and 'int' */ }
    void func3() { /* actions with A and 'int' */ }
}

但我想避免在func0func1 中复制粘贴。

我也可以将常见的Foo 重命名为FooBase 并简单地从中继承Foo,但在这种情况下我不能使用常见的情况

Foo<float, float> a;

确实存在哪些方法可以让我同时使用这两种方法

Foo<float, float> a;

Foo<float, int> b;

没有复制和粘贴通用Foo的代码到专业化?

我对 c++11 和更早的标准兼容性都感兴趣。

【问题讨论】:

  • Piotr S 在这里给出了很好的答案stackoverflow.com/questions/27444624/…
  • @JayMiller,情况略有不同——我不仅想更改部分情况的基本方法,还想在特殊类型中添加特定方法。

标签: c++ templates c++11 metaprogramming


【解决方案1】:

这似乎对我有用。

template <typename A, typename B>
struct Foo;

template <typename A, typename B>
struct FooBase
{
    Foo<A, B>& func0()
    {
        cout << "FooBase:func0\n";
        return static_cast<Foo<A, B>&>(*this);
    }

    void func1() { cout << "FooBase::func1\n"; }
    void func2() { cout << "FooBase::func2\n"; }
};

template <typename A, typename B>
struct Foo : public FooBase<A, B> {
};

template <typename A>
struct Foo<A, int> : public FooBase<A, int>
{
    void func2() { cout << "Foo<A, int>::func2\n"; }
    void func3() { cout << "Foo<A, int>::func3\n"; }
};

如果您最终需要在 FooBase 中定义 Foo,您可能需要使用 CRTP 技巧将派生类作为模板参数传递给 FooBase,但对于简单的事情,我认为前向声明就足够了。

【讨论】:

    【解决方案2】:

    您可以使用标签调度:

    template <typename A, typename B>
    struct Foo  
    {
        decltype(func0(std::is_same<B, int>{})) func0()
        {
            return func0(std::is_same<B, int>{});
        }
        void func1() { /* common actions with A and B */ }
        void func2() { /* common actions with A and B */ }
    private:
        Foo& func0(std::true_type)  { func0_common(); return *this; }
        void func0(std::false_type) { func0_common(); }
        void func0_common() { /* common actions with A and B */ }
    };
    

    【讨论】:

    • 谢谢,这给出了初始问题的答案,但据我所知,我不能使用这种方法添加多个 func0() 的专业化(例如,如果我还想要 func0() float?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-12
    • 2013-06-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多