C++ template partial specialization with inheritance

倖福魔咒の 提交于 2020-01-02 07:31:29

问题


I need partial specialization of the struct, but I'd like also use some common functionality. For example, suppose I have the next type:

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 */ }
}

Then I want specialize it for one of the template parameters - for example, I want consider special case when B is int, and I want to preserve func0 and func1 behaviour exactly the same as in common Foo (or course, func0() must return my specialized Foo& for int), func2 I want rewrite (suppose that I have more efficient implementation of it for integers), and I also want add func3() only for my specialized Foo.

Of course, I can simpy write the following:

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' */ }
}

but I'd like to avoid copy-paste in func0 and func1.

I also can rename common Foo to something like FooBase and simply inherit Foo from it, but in this case I can't use the common case as

Foo<float, float> a;

What methods does exist for allow me using both

Foo<float, float> a;

and

Foo<float, int> b;

without copying and pasting common Foo's code to specialization?

I'm interested in both c++11 and earlier standard compatibility.


回答1:


This seems to work for me.

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"; }
};

If you wind up needing the definition of Foo within FooBase, you may need to use the CRTP trick of passing the derived class as a template parameter to FooBase, but for simple things I think the forward declaration is sufficient.




回答2:


You can use tag-dispatching:

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 */ }
};


来源:https://stackoverflow.com/questions/27453449/c-template-partial-specialization-with-inheritance

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!