несколько статических интерфейсов с зависящим от реализации типом функции-члена - PullRequest
0 голосов
/ 01 июня 2019

У меня есть два интерфейса, которые я хочу использовать с CRTP для статического полиморфизма.Одна из них содержит функцию, типы которой в сигнатуре зависят от реализации.

Эта проблема выглядит как то, что было задано здесь без решения.Решение, которое я придумал, включает дополнительную шаблонную структуру, определяющую тип.Этот шаблон затем специализируется для реализации, избегая ошибки «недопустимое использование неполного типа».

Здесь мой код

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

Что мне не нравится в этом коде, так это то, что Interface2 иtypeHelp зависит от параметра шаблона impl1.Это работает для моего конкретного случая, когда реализация 2 основана на impl1, но не будет, если реализация 2 не была.Интересно, есть ли более общее и элегантное решение этой проблемы?

1 Ответ

0 голосов
/ 01 июня 2019

мой плохой; немного больше поиска, и я бы нашел ответ. На этой ссылке Энди Дж указывает, что можно специализировать шаблон класса с помощью шаблонного класса. Результат более чистый, чем раньше

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