具有实现类型的成员函数类型的多个静态接口

时间:2019-06-01 12:10:05

标签: c++ crtp interface-implementation static-polymorphism

我有两个接口想与CRTP一起使用以实现静态多态性。其中之一包含一个函数,其签名中的类型与实现有关。

这个问题看起来像是here提出的没有解决方案的问题。我想出的解决方案包括定义类型的附加模板化结构。然后,该模板专门用于实现,避免了“无效使用不完整类型”错误。

这是我的代码

#include <iostream>
#include <memory>

template<class impl1>
struct Interface1 {
    double foo() { return static_cast<impl1*>(this)->fooimpl();}
};

template<class impl1, class impl2>
struct typeHelp;

template<class impl1, class impl2>
struct Interface2 {
    void bar(typename typeHelp<impl1,impl2>::type value) {
        static_cast<impl2*>(this)->barimpl(value);
    }
};

//Implementation2 pre declaration
template<class impl1>
struct Implementation2;

//Partial specialization of templated typeHelp
template<class impl1>
struct typeHelp<impl1, Implementation2<impl1>> {
    using type = int;
};

//Implementation2
template<class impl1>
struct Implementation2 : public Interface2<impl1, Implementation2<impl1>> {
    std::shared_ptr<Interface1<impl1>> imp1;
    void barimpl(typename typeHelp<impl1,Implementation2>::type value) {
        std::cout << imp1->foo() << " " << value << std::endl;
    }
};

//Implementation1
struct Implementation1 : public Interface1<Implementation1> {
    double fooimpl() {return 0.;}
};

int main()
{
    Implementation2<Implementation1> obj;
    obj.imp1 = std::make_shared<Implementation1>();
    obj.bar(4);
}

我在这段代码中不喜欢接口2和typeHelp取决于模板参数impl1。这适用于我的特定情况,其中Implementation2是针对impl1进行模板化的,但是如果实现2不是,则不会。我想知道是否有一个更通用,更优雅的解决方案。

1 个答案:

答案 0 :(得分:0)

我的坏;多一点搜索,我会找到答案的。在此link上,Andy G指出可以使用模板化的类来专门化类模板。结果比以前更干净

#include <iostream>
#include <memory>

//Interface1.hpp
template<class impl1>
struct Interface1 {
    double foo() { return static_cast<impl1*>(this)->fooimpl();}
};

//Interface2.hpp
template<class impl2>
struct typeHelp;

template<class impl2>
struct Interface2 {
    void bar(typename typeHelp<impl2>::type value) {
        static_cast<impl2*>(this)->barimpl(value);
    }
};

//Implementation2.hpp
template<class impl1>
struct Implementation2;

//specialization of typeHelp with templated class
template<class impl1>
struct typeHelp<Implementation2<impl1>> {
    using type = int;
};

//Actual implementation of Implementation2
template<class impl1>
struct Implementation2 : public Interface2<Implementation2<impl1>> {
    std::shared_ptr<Interface1<impl1>> imp1;
    void barimpl(typename typeHelp<Implementation2<impl1>>::type value) {
        std::cout << imp1->foo() << " " << value << std::endl;
    }
};

//Implementation1.hpp
struct Implementation1 : public Interface1<Implementation1> {
    double fooimpl() {return 0.;}
};

//Main.hpp
int main()
{
    Implementation2<Implementation1> obj;
    obj.imp1 = std::make_shared<Implementation1>();
    obj.bar(4);
}