Не указывать аргументы шаблона при создании экземпляра класса шаблона из другого экземпляра класса шаблона.

Я хочу пропустить какой-либо параметр шаблона T1,T2 когда создать экземпляр класса DeriveGenerator<T3,T4,T1,T2> чтобы успокоить мою жизнь.

Вот предельно упрощенная версия того, с чем я сталкиваюсь.

Моя библиотека:-

Важной частью является объявление класса. (this line)
Их внутреннее содержание - просто наполнитель.

template<class T1,class T2>class BaseGenerator{ //<-- this line
    public: std::pair<T1*,T2*> generateBase(){ 
        /** actually create T3,T4 internally */
        return std::pair<T1*,T2*>(nullptr,nullptr);
    }
};
template<class T3,class T4,class T1,class T2>class DeriveGenerator{ //<-- this line
    public: Base<T1,T2>* base;
    public: std::pair<T3*,T4*> generateDerive(){ 
        auto pp=base->generateBase();
        return std::pair<T3*,T4*>((T3*)(pp.first),(T4*)(pp.second));
    }
};

Пользователь: -

class B1{};class B2{};
class B3:public B1{};
class B4:public B2{};
int main() {
    //v this is what I have to
    BaseGenerator<B1,B2> baseGen;
    DeriveGenerator<B3,B4,B1,B2> deriveGen;  //so dirty #1
    deriveGen.base=&baseGen;
    deriveGen.generateDerive();
}

Вопрос

Можно ли сделать линию #1 очиститель?
Я хочу тип deriveGen зависит от типа baseGen,

Вот что я хочу: -

BaseGenerator<B1,B2> baseGen;
DeriveGenerator<B3,B4> deriveGen;   //<-- modified
deriveGen.base=&baseGen;

или хотя бы что-то вроде:

BaseGenerator<B1,B2> baseGen;
DeriveGenerator<B3,B4, DECLARATION_TYPE(baseGen) > deriveGen;   //<-- modified
deriveGen.base=&baseGen;

Я прочитал (до сих пор не знаю):

Я даже не знаю, возможно ли это.

"decltype", кажется, самая близкая подсказка, но я не могу найти способ применить это к этому случаю.
Я думаю, что, возможно, придется разделить его на T1,T2.... (?)

редактировать

В реальном случае baseGen это нестатическое поле некоторых классов, которое еще не создано, например

class Holder{
    public: BaseGenerator<B1,B2> baseGen;
};

Поэтому во время декларирования deriveGenЯ не могу достичь реального случая baseGen,
Это сложная часть.

Я могу сослаться baseGenТип через decltype, хоть.
(извините, что не упомянул об этом)

3 ответа

Решение

Не уверен, что понимаю, что вы хотите, но... я полагаю, вы можете определить DeriveGenerator в этом случае

template <typename, typename, typename>
class DeriveGenerator;

template <typename T3, typename T4, typename T1, typename T2>
class DeriveGenerator<T3, T4, BaseGenerator<T1, T2>>
 {
   public:
      BaseGenerator<T1,T2>* base;

   public:
      std::pair<T3*,T4*> generateDerive ()
       { 
         auto pp=base->generateBase();
         return std::pair<T3*,T4*>((T3*)(pp.first),(T4*)(pp.second));
       }
 };

и используйте его следующим образом

BaseGenerator<B1,B2> baseGen;
DeriveGenerator<B3,B4,decltype(baseGen)> deriveGen; 

Это если вы заинтересованы в T1 а также T2 типы; если вы заинтересованы только в BaseGenerator<T1, T2> ты можешь просто написать

template <typename T3, typename T4, typename Tbase>
class DeriveGenerator
 {
   public:
      Tbase * base;

   public:
      std::pair<T3*,T4*> generateDerive ()
       { 
         auto pp=base->generateBase();
         return std::pair<T3*,T4*>((T3*)(pp.first),(T4*)(pp.second));
       }
 };

Если вы можете изменить определение DeriveGenerator на:

template<class T3, class T4, class BaseT>
class DeriveGenerator{
public:
    BaseT* base = nullptr;

    std::pair<T3*, T4*> generateDerive(){ 
        auto pp = base->generateBase();
        return {(T3*)(pp.first), (T4*)(pp.second)};
    }
};

Вы можете использовать:

BaseGenerator<B1, B2> baseGen;
DeriveGenerator<B3, B4, decltype(baseGen)> deriveGen;

Еще я предлагаю создать помощника:

 template <typename B3, typename B4, typename B1, typename B2>
 DeriveGenerator<B3, B4, B1, B2>
 MakeDerived(BaseGenerator<B1, B2>& baseGen)
 {
     DeriveGenerator<B3, B4, B1, B2> deriveGen;
     deriveGen.base = &baseGen;
     return deriveGen;
 }

а затем использовать

BaseGenerator<B1,B2> baseGen;
auto deriveGen = MakeDerived<B3, B4>(baseGen);

Я думаю, что проще нажать T1 а также T2 параметры шаблона для DeriveGenerator в реальный generateDerive сам метод:

template<class T3,class T4>
class DeriveGenerator{ 
    public: 
    template<class T1, class T2, template<class, class> class Base>
    std::pair<T3*,T4*> generateDerive(Base<T1, T2>* base){
        static_assert(std::is_base_of<T1, T3>::value && std::is_base_of<T2, T4>::value, "T1 should be base of T3 and T2 should be base of T4"); 
        auto pp=base->generateBase();
        return std::pair<T3*,T4*>((T3*)(pp.first),(T4*)(pp.second));
    }
};

демонстрация

Теперь вы можете назвать это так:

BaseGenerator<B1,B2> baseGen;
DeriveGenerator<B3,B4> deriveGen;
deriveGen.generateDerive(&baseGen);

Я добавил static_assert в DeriveGenerator::generateDerive что обеспечило правильное соединение основание / производное с использованием std::is_base_of так что вы получите ошибку компилятора, если вы случайно испортите параметры шаблона.

class B5{}; // new class B5 nobody inherits from
BaseGenerator<B1, B5> bad_baseGen;
deriveGen.generateDerive(&bad_baseGen);
Другие вопросы по тегам