C++ 已知类集合中的反射
我试图遍历一个对象层次结构,而对象层次结构是由一组已知的类组成的,这些类通过组合组合而成。我想构建一个对象模型,以图形方式显示层次结构/组合。构图是根据一些规则完成的,但它是流动和灵活的 相当多的类(25+)可用,构建块的数量正在增加。如果我在其他类型中搜索每种类型,那么我们有大量可能的组合 我可以构建一个大表,在其中搜索给定类型的每个其他对象,并递归地构建对象模型,但可能有更好的方法,因此我在这里询问专家 是否可能知道在运行时特定类型上是否存在函数/成员变量 我的示例代码如下所示:C++ 已知类集合中的反射,c++,templates,metaprogramming,C++,Templates,Metaprogramming,我试图遍历一个对象层次结构,而对象层次结构是由一组已知的类组成的,这些类通过组合组合而成。我想构建一个对象模型,以图形方式显示层次结构/组合。构图是根据一些规则完成的,但它是流动和灵活的 相当多的类(25+)可用,构建块的数量正在增加。如果我在其他类型中搜索每种类型,那么我们有大量可能的组合 我可以构建一个大表,在其中搜索给定类型的每个其他对象,并递归地构建对象模型,但可能有更好的方法,因此我在这里询问专家 是否可能知道在运行时特定类型上是否存在函数/成员变量 我的示例代码如下所示: #incl
#include <iostream>
struct Generic {};
struct SimpleType {int toString(){return 0;}};
enum ETypeVal{eVal1 = 0, eVal2 = 1, eVal3 = 2};
template <typename ETypeVal val>
struct Hello
{
int toString(){return 0;}
};
template <> struct Hello<eVal2>
{
int toString(){return 1;}
};
template <> struct Hello<eVal3>
{
};
template <class Type>
class TypeHasToString
{
public:
typedef bool Yes;
typedef short No;
static bool const value = (sizeof(HasToString<Type>(0)) == sizeof(Yes));
private:
template <typename T, T> struct TypeCheck;
template <typename T> struct ToString
{
typedef int (T::*fptr)();
};
template <typename T> static Yes HasToString(TypeCheck< typename ToString<T>::fptr, &T::toString >*);
template <typename T> static No HasToString(...);
};
int main(int argc, char *argv[])
{
// all this works fine
std::cout << TypeHasToString<Generic>::value << std::endl;
std::cout << TypeHasToString<SimpleType>::value << std::endl;
std::cout << TypeHasToString<Hello<eVal1>>::value << std::endl;
std::cout << TypeHasToString<Hello<eVal2>>::value << std::endl;
std::cout << TypeHasToString<Hello<eVal3>>::value << std::endl;
// Unable to deduce for type that are not known at compile time
// Is it possible to remove this limitation ?
for(int val = eVal1; val <= eVal3; val++)
{
std::cout << TypeHasToString< Hello< (ETypeVal)val > >::value << std::endl;
}
return 0;
}
#包括
结构泛型{};
结构SimpleType{int-toString(){return 0;}};
枚举ETypeVal{eVal1=0,eVal2=1,eVal3=2};
模板
结构你好
{
int-toString(){return 0;}
};
模板结构Hello
{
int-toString(){return 1;}
};
模板结构Hello
{
};
模板
类类型hastoString
{
公众:
typedef bool是;
typedef短No;
静态布尔常量值=(sizeof(HasToString(0))==sizeof(Yes));
私人:
模板结构类型检查;
模板结构ToString
{
typedef int(T::*fptr)();
};
模板静态Yes HasToString(TypeCheck*);
模板静态无HasToString(…);
};
int main(int argc,char*argv[])
{
//所有这些都很好
STD::CUT我认为在这种情况下需要运行时多态性。使用接口代替模板来解决此类问题。接口将给出关于对象中方法的知识,但不会对成员变量表示任何说明。因此在标准C++中没有可用的反射。(C++提供的唯一东西是Type信息操作程序,在某些情况下可能会帮助您),您可以尝试为编译器找到一些扩展,这些扩展将为您提供反射机会。
我认为在这种情况下您需要运行时多态性。对于此类问题,请使用接口而不是模板。接口将提供有关对象中方法的知识,但不会说明成员vaRiabess。所以在标准C++中没有反射可用(C++提供的唯一东西是Type信息操作程序,在某些情况下可能会帮助你)你可以尝试为编译器找到一些扩展,这样会给你带来反射机会。 < P>我们在C++中没有运行时反射。但是我们有不同的东西,大多数C++程序员喜欢比反射更好;-----
如果我理解你的问题,你需要构建某种对象浏览器,你知道你所有的对象类型。所谓“你知道你所有的对象类型”,我的意思是“你不会从一个没有编码的dll中得到一个指针另一端的对象”
这样,也许你可以使用.Load库是用来迭代聚合的,在这样做时,检索每个聚合成员的数据和类型。它就像是结构成员上的迭代器,如果我必须把它放在一个华丽的方式上。当然可以用你的自定义类型。
< P>我们在C++中没有运行时反射。但是我们有D。不同的东西,大多数C++程序员喜欢比反射好;-)
如果我理解你的问题,你需要构建某种对象浏览器,你知道你所有的对象类型。所谓“你知道你所有的对象类型”,我的意思是“你不会从一个没有编码的dll中得到一个指针另一端的对象”
那么,也许您可以使用?所说的库是为迭代聚合而设计的,在这样做的同时,检索每个聚合成员的数据和类型。如果我必须以华丽的方式将它放在结构成员上,它就像迭代器一样。当然,您可以使用自定义类型进行迭代。如果在编译时不这样做,您在运行时无法知道。在编译时,你需要知道一个函数的代码。你可以用它制作一个宏,用于任何你想检查的函数。(宏免责声明:在这种情况下,宏是好的,这就是BOOST_MPL_XXX_TEMPLATE_DEF的工作原理)
或者,还有dsign提到的boost::fusion。但我更喜欢另一个:boost::reflect(实际上在boost中没有)。宏语法更简单(不需要在宏中提及类型),代码非常轻量级。然后还有完整的功能boost::mirror(),在boost中还没有,它更完整,甚至有一个代码生成器为您创建宏调用和java风格的运行时反射。如果在编译时没有,您在运行时无法知道。对于一个函数,您在编译时就可以知道代码。您可以从中生成一个宏,用于任何要编译的函数见鬼。(宏免责声明:在这种情况下,宏是好的,这就是BOOST\u MPL\u XXX\u TEMPLATE\u DEF的工作原理)
或者,还有dsign提到的boost::fusion。但我更喜欢另一个:boost::reflect(实际上在boost中没有)。宏语法更简单(不需要在宏中提及类型),代码非常轻量级。然后还有完整的功能boost::mirror(),在boost中还没有,它更完整,甚至有一个代码生成器来为您创建宏调用和java风格的运行时反射。我已经使用boost::mpl来进行迭代和打印值。大多数情况下,如果没有这些,应该是可能的,但我强烈建议使用它。此外,我还修复了您的co中的一些问题de.您可能还希望使用BOOST_HAS_XXX而不是您的自制解决方案(您的SFINAE风格相当笨拙)
#包括
#包括
#include <iostream>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/range_c.hpp>
#include <boost/mpl/transform.hpp>
#include <boost/mpl/for_each.hpp>
struct Generic {};
struct SimpleType {int toString(){return 0;}};
enum ETypeVal{ eVal1 = 0, eVal2 = 1, eVal3 = 2};
template <ETypeVal val>
struct Hello
{
int toString(){return 0;}
};
template <> struct Hello<eVal2>
{
int toString(){return 1;}
};
template <> struct Hello<eVal3>
{
};
template <class Type>
class TypeHasToString
{
public:
typedef bool Yes;
typedef short No;
private:
template <typename T, T> struct TypeCheck;
template <typename T> struct ToString
{
typedef int (T::*fptr)();
};
template <typename T> static Yes HasToString(TypeCheck< typename ToString<T>::fptr, &T::toString >*);
template <typename T> static No HasToString(...);
public:
static bool const value = (sizeof(HasToString<Type>(0)) == sizeof(Yes));
};
template<typename val>
struct make_hello { typedef Hello< ETypeVal(val::value)> type; };
struct print_seq {
template<typename T>
void operator()(const T&) const {
std::cout << T::value << std::endl;
}
};
int main()
{
using namespace boost::mpl;
// maybe have a last enum here
typedef range_c<int, eVal1, eVal3 + 1>::type range;
// range has no clear so we need the inserter
typedef transform<range, make_hello<_1>, back_inserter< vector0<> > >::type hellos;
typedef transform< hellos, TypeHasToString<_1> >::type booleans;
// namespace for clarity
boost::mpl::for_each<booleans>( print_seq() );
return 0;
}