C++模板的部分特化与继承

5

我需要对 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()必须返回我的专门针对intFoo&),func2我想要重写(假设我有更有效率的整数实现),并且我还想为我的专门Foo添加func3()

当然,我可以简单地编写以下内容:

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和早期标准的兼容性都很感兴趣。


4
Piotr S在这里做出了很好的回答:https://dev59.com/7Ybca4cB1Zd3GeqPQQAd - Jay Miller
@JayMiller,这是稍微不同的情况 - 我不仅想为部分情况更改基本方法,我还想在专门的类型中添加特定的方法。 - avtomaton
2个回答

9

这对我来说似乎有效。

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,但对于简单的事情,我认为前向声明已足够。

1
你可以使用标签派发技术:
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()的专业化(例如,如果我还想要floatfunc0() - avtomaton

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接