我放弃了,请帮忙解释一下这个行为.下面我给出的例子是我能想到的最简单的例子,但是总结了这个问题(在Cygwin上使用g 4.9.2,启用了c14).我想创建一个类似于std :: mem_fn的类.这是我的课:
template <class R,class T,R(T::*P)() const > struct property { static R get(const T& t) { return (t.*P)(); } };
其中R是返回类型,T是我感兴趣的对象的类型.第三个模板参数是一个指向成员函数的指针.到现在为止还挺好.
然后我创建一个简单的类,它保存一个整数如下
class data_class { public: unsigned get_data() const { return m_data; } private: unsigned m_data; };
现在我创建了从data_class继承的两个类,如下所示
struct my_classA : public data_class { using data = property<unsigned,data_class,&data_class::get_data>; }; //same as my_classA,only templated template <int I> struct my_classB : public data_class { using data = property<unsigned,&data_class::get_data>; };
它们具有完全相同的内部typedef,但是my_classB是模板化的.以下类型在理论上应该是一样的:
using target_t = property<unsigned,&data_class::get_data>; using test1_t = typename my_classA::data; using test2_t = typename my_classB<1>::data;
但是我的编译器说只有test1_t和target_t是一样的.显然为test2_t推出的类型
property<unsigned int,(& data_class::get_data)> >
这个类型在指向成员函数的指针周围有这些括号.为什么test2_t与target_t不一样?这是完整的代码,以防您想在系统上尝试.任何帮助深表感谢.
#include <type_traits> class data_class { public: unsigned get_data() const { return m_data; } private: unsigned m_data; }; //takes return type,class type,and a pointer to member function //the get function takes an object as argument and uses the above pointer to call the member function template <class R,R(T::*P)() const > struct property { static R get(const T& t) { return (t.*P)(); } }; struct my_classA : public data_class { using data = property<unsigned,&data_class::get_data>; }; //used to produce informative errors template <class T> struct what_is; //all 3 types below should,in theory,be the same //but g++ says that test2_t is different using target_t = property<unsigned,&data_class::get_data>; using test1_t = typename my_classA::data; using test2_t = typename my_classB<1>::data; static_assert(std::is_same<target_t,test1_t>::value,""); //this passes static_assert(std::is_same<target_t,test2_t>::value,""); //this does not int main() { what_is<test1_t> t1; what_is<test2_t> t2; }
解决方法
我用c 11运行你的代码,因为我对C14还不太熟悉.但是我更换的是使用typedef的(别名),并简化了一些代码.没有什么可以影响其输出.
通过在继承的classB模板中添加一个typename T来获得所需的结果,当实例化时,它将用T代替R,所以在这种情况下是“unsigned”.
#include <iostream> #include <type_traits> template <typename R,typename T,R(T::*P)() const> struct property { static R get(const T& t) { return (t.*P)(); } }; struct data_class { private: unsigned m_data; public: unsigned get_data() const { return m_data; } }; struct my_classA : public data_class { typedef property<unsigned,&data_class::get_data> data; }; template <typename T,int> struct my_classB : public data_class { typedef property<T,&data_class::get_data> data; }; int main() { typedef typename my_classA::data normClassA; typedef typename my_classB<unsigned,1>::data tmplClassB; std::cout<< std::is_same< property<unsigned,&data_class::get_data>,normClassA >::value <<std::endl; std::cout<< std::is_same< property<unsigned,tmplClassB >::value <<std::endl; }
结果是这样的:
~$g++ -std=c++11 test.cpp ~$./a.out 1 1
我认为该问题与类模板实例化标准有关,因为当我最初尝试打印两个类的sizeof时,my_classA :: data返回1,但是my_classB< 1> :: data以compiller错误结束.为什么会发生这种情况,我还是很模糊的.在技术上它应该已经实例化了类模板很好.也许这是classB模板中虚拟实例化的属性.我会再看看这个,但如果你找到答案,请张贴.这是一个有趣的!
编辑:原始代码在Cygwin GCC 4.8.2中正常工作.结果是1和1.也许这只是一个gcc4.9.2编译器问题.