Не указывать аргументы шаблона при создании экземпляра класса шаблона из другого экземпляра класса шаблона.
Я хочу пропустить какой-либо параметр шаблона 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;
Я прочитал (до сих пор не знаю):
- Пропуск аргументов в шаблонах C++
- Пропуск параметра шаблона C++
- Разница при пропуске списка аргументов шаблона C++
Я даже не знаю, возможно ли это.
"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);