成员模板函数的访问控制
Posted
技术标签:
【中文标题】成员模板函数的访问控制【英文标题】:Access control to member template functions 【发布时间】:2013-06-18 23:39:26 【问题描述】:我正在开发一个使用 SFINAE 检测成员函数是否存在的项目。我遇到了以下示例的问题:
class Base
private:
template <class T>
void foo( T t )
void snarf()
;
class Derived : public Base
public:
template <class T>
void bar( T t )
foo( t ); // shouldn't be possible
snarf(); // bug in gcc, correctly identified as error in clang
;
问题似乎是在尝试访问继承的函数时,派生类中没有尊重基类中的访问控制(例如私有)。 foo 和 snarf 都应该不能从派生类中访问。因此,当我尝试测试某个派生类是否具有某些功能时,它会错误地访问基类以查找匹配项。
在 g++ 4.8.1 中,错误地允许调用 foo 和 snarf 发生,我很确定这是这个错误的一个实例:http://gcc.gnu.org/bugzilla/show_bug.cgi?id=41437
在clang++ 3.3中,调用snarf被正确识别为错误,但允许调用foo,看来也应该是错误。这看起来像clang ++中的错误吗? (我已经发布了一个错误报告,以防万一它原来是http://llvm.org/bugs/show_bug.cgi?id=16410)
鉴于这很可能是两个编译器中的一个错误,是否有任何聪明的解决方法可以用来检测派生实际上无法访问 foo?我实际使用的方式如下:
template <class T, class T2, class Unused = void>
struct has_member_foo : std::false_type ;
当调用 declval<T&>().foo(declval<T2&>())
解析为有效函数 ala Checking a member exists, possibly in a base class, C++11 version 时,has_member_foo
专门从 std::true_type
扩展。当派生类继承 foo
的私有版本时,我需要它失败。
【问题讨论】:
【参考方案1】:当您编写尝试调用bar
的代码时,编译器会说什么?
Derived d;
d.bar<int>(42);
如果它在那里显示错误,那么我认为事情正在按预期工作。在您实际编写使用模板方法的代码之前,没有什么可编译的,因此如果您使用的是不太智能的编译器,您可能看不到任何错误。
你甚至可以像这样定义 bar:
template <class T>
void bar( T t )
foo( t );
snarf();
snorf();
divideByZero();
asdf--+|&*
只要您从不尝试使用 bar,它仍然会编译(使用某些编译器)。
【讨论】:
看来CLang++ 3.3还是没有发现错误,即使main调用了它。 在实际实例化类似上面的代码时,g++和clang++都会找不到错误。以上是关于成员模板函数的访问控制的主要内容,如果未能解决你的问题,请参考以下文章