如何获取所有必要的信息,以便在运行时从下面的代码中打印“dynamic_cast(p)->eval()”的等效更快的代码字符串? (请在代码示例下面找到代码生成器背景/上下文)
#include<iostream>
#include<string>
#include"lib_typename.hpp" // template<typename T> typename_of<T>() returns string "T"; cf., e.g., in Boost
struct X;
struct A{
virtual std::string my_typename()const{ return typename_of<A>(); }
virtual ~A(){};
};
struct B{
virtual std::string my_typename()const{ return typename_of<B>(); }
virtual void eval()=0;
};
template<typename T>
struct C: A,B{
virtual std::string my_typename()const{ return typename_of<C<T>>(); }
void eval(){}
};
int main(){
C<X> c;
A& p = c;
dynamic_cast< B& >(p).eval(); // <-- I can generate that, but it is slow.
static_cast< C<X>& >(p).eval(); // <-- This is fast, but where do I get the string "C<X>" from?
// possible ways to find the string:
std::cout << p.my_typename() << "\n"; // necessitates tons of boilerplate.
std::cout << typeid(C<X>).name() << "\n"; // returns gibberish.
}
解释:“dynamic_cast(p).eval()”行是由我构建的代码生成器生成的。在生成时,我手头上的信息是
A& p
指的是 B
的非抽象派生。
我目前最喜欢的是样板选项,这样我的代码生成器最终可以生成更快的代码“static_cast
背景:我的应用程序是一个基于模板的代码生成器。有些人可能会将此本身称为 xy 问题,但我的 x 工作(除了上面的,我可以忍受)令人满意。这个问题很模糊,因为我同样对不识别字符串“
C<X>
”的替代解决方案感到满意。
最后评论:我添加了模板参数
X
作为最小反例,以表明找到 A
和 B
的第一个共同继承者不足以解决问题。
基于 @CraigEstey 的非凡“盲目猜测”,以下解决方案遵循样板方法,同时通过 CRTP 继承替换它来减轻一些样板:
// add struct
struct Crtp<typename T=void>{
virtual std::string my_typename()const{ return typename_of<T>(); }
};
struct B:Crtp<B>{
virtual void eval()=0;
};
template<typename T>
struct C: A,B,Crtp<C<T>>{
void eval(){}
};
字符串
Crtp<structname>
本质上应该使样板virtual std::string my_typename()const{ return typename_of<structname>(); }
变得不必要,但我还没有测试过它。我还不确定。欢迎大家提出解决方案。