c – 无效的模板依赖成员函数模板推导 – 认为我正在尝试使用std
我有一个继承自基类模板的类模板.
基类模板有一个带有成员函数模板的数据成员,我想从我的超类中调用它. 我知道为了消除对成员函数模板的调用的歧义,我必须使用template关键字,我必须在超类中明确地引用它. this-> base_member_obj.template member_function< int>(); 所有这一切都很好,除了我正在使用的代码库导致了导入整个命名空间std的相当不幸的错误,而我试图调用的模板成员函数被称为set.框架中的某个地方包含了std :: set,这导致GCC认为我正在尝试声明一个std :: set而不是调用成员函数集. GCC 4.7抛出错误无效使用’class std :: set’ 请参阅下面的示例以显示错误.如果您使用命名空间std注释掉代码编译正常. 遗憾的是,我不可能遍历整个代码库,删除每个使用的命名空间std调用,并使用std ::为std命名空间内的任何内容添加前缀. 还有其他方法吗? #include <set> using namespace std; // comment this out to compile fine struct blah { template<typename T> void set() { } }; template<typename T> struct base { blah b; }; template<typename T> struct super : base<super<T>> { void fun() { this->b.template set<int>(); // this line breaks } }; int main() { super<int> s; s.fun(); return 0; } 解决方法
嗯,这对我们的C推动者来说相当尴尬.
这是G中的一个错误,也出现在Comeau Test Drive中.这不是语言本身的缺陷.问题源于解析的左右性质以及C语法模糊的方式. 将嵌套名称说明符中的非成员非基类模板用于基类模板的typedef是合法的.在这样的上下文中,在>之后可以出现与所访问的类没有特殊关系的类模板. #include <tuple> template< typename t > struct get_holder { typedef std::tuple< t > type; }; template< typename ... ts > struct inherits : get_holder< ts >::type ... { inherits( ts ... v ) : get_holder< ts >::type( v ) ... {} template< typename tn > void assign_one( inherits &o ) { this->get_holder< tn >::type::operator= ( o ); } // <- here! }; int main() { inherits< int,char,long > icl( 3,'q',2e8 ); icl.assign_one< char >( icl ); } 由于C从左到右解析,当解析器命中 – >时,它必须在继续之前解析get_holder.标准有一个特殊条款§3.4.5/ 1 [basic.lookup.classref]:
强调我的 – 尽管模板之间出现了模板关键字,但G似乎遵循了这个逻辑.和标识符集.此外,假设它正沿着这条路线走下去,它应该将歧义标记为错误,而不是试图选择非成员. 当模板关键字出现时,标准的措辞似乎存在缺陷,但它不应该引起您看到的混乱. §14.2[temp.names]:
强调我的,该文本是错误的,应该读作“假定名称不是为成员模板命名”,因为如上图所示,它可能是嵌套名称说明符的一部分.如果文本字面上按原样,那么它可以被解释为在我的插图中需要模板关键字,因此可以指示以下非成员模板(假设语言完全支持这样的构造),然后你的如G所见,程序可能会被误解. 但设计意图很明确,你不需要添加一个人工嵌套的名称说明符blah ::,虽然这是一个合法的解决方法. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |