Я ищу обходной путь к отсутствию виртуальных шаблонных функций в C ++.В идеале я хочу сохранить свои производные классы в векторе, выполнить итерацию по ним и вызвать правильную функцию, поэтому в псевдокоде:
template<typename T>
struct Output
{
...
};
struct Base
{
template<typename T>
virtual void doSomething(Output<T>& out) = 0;
};
struct DerivedA : public Base
{
DerivedA(const char* filename) {...}
template<typename T>
void doSomething(Output<T>& out) final
{
...
}
};
struct DerivedB : public Base
{
DerivedB(const char* filename) {...}
template<typename T>
void doSomething(Output<T>& out) final
{
...
}
};
int main()
{
std::vector<Base*> vec;
vec.push_back(new DerivedA("data1.bin"));
vec.push_back(new DerivedB("data2.bin"));
vec.push_back(new DerivedA("data3.bin"));
vec.push_back(new DerivedA("data4.bin"));
Output<float> outF;
Output<double> outD;
Output<int> outI;
for (auto e : vec)
{
e->doSomething(outF);
e->doSomething(outD);
e->doSomething(outI);
}
return 0;
}
Я бы предпочел, чтобы обходной путь был«безболезненный» и не многословный, насколько это возможно (поскольку я использую шаблоны, чтобы избежать переопределения одной и той же функции n раз для n различных типов в первую очередь).Я думал о том, чтобы сделать себя vtable с помощью std :: map и сделать несколько dynamic_casts.Я ищу какие-нибудь лучшие идеи или даже краткую реализацию этой идеи, если вы считаете ее лучшей в этом сценарии.Я ищу решение, которое в идеале должно быть наименее навязчивым, и к которому очень легко добавлять новые классы.
Редактировать: я нашел обходной путь, но он включает в себя некоторые подробности (но, по крайней мере, избегает нетривиальныхдублирование кода):
struct Base
{
virtual void doSomething(Output<int>& out) = 0;
virtual void doSomething(Output<float>& out) = 0;
virtual void doSomething(Output<double>& out) = 0;
private:
template<typename T>
void doSomething(Output<T>& out)
{
std::cout << "Base doSomething called with: " << typeid(T).name() << "\n";
}
};
struct DerivedA : public Base
{
void doSomething(Output<int>& out) final
{
doSomething<int>(out);
}
void doSomething(Output<float>& out) final
{
doSomething<float>(out);
}
void doSomething(Output<double>& out) final
{
doSomething<double>(out);
}
private:
template<typename T>
void doSomething(Output<T>& out)
{
std::cout << "DerivedA doSomething called with: " << typeid(T).name() << "\n";
}
};
struct DerivedB : public Base
{
void doSomething(Output<int>& out) final
{
doSomething<int>(out);
}
void doSomething(Output<float>& out) final
{
doSomething<float>(out);
}
void doSomething(Output<double>& out) final
{
doSomething<double>(out);
}
private:
template<typename T>
void doSomething(Output<T>& out)
{
std::cout << "DerivedB doSomething called with: " << typeid(T).name() << "\n";
}
};
Кто-нибудь может лучше понять, как я могу сделать это без переопределения одних и тех же функций снова и снова?В идеале это будет определено один раз в базовом классе, CRTP, кажется, не помогает.Динамическое приведение похоже на другой вменяемый вариант.