2013-06-21 28 views
3

我正在使用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

在铛++ 3.3,调用SNARF被正确识别为错误,但foo被允许被调用,这似乎也应该是一个错误。这看起来像是一个在铿锵++错误? (我已经发布了一个错误报告,以防万一结果为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 {}; 

has_member_foo呼吁declval<T&>().foo(declval<T2&>())解析为ALA Checking a member exists, possibly in a base class, C++11 version有效的功能时,专门从std::true_type延伸。当派生类继承foo的私有版本时,我需要这样做。

回答

0

当您编写试图拨打bar的代码时,编译器会说什么?

Derived d; 
d.bar<int>(42); 

如果它在那里显示错误,那么我认为事情按预期工作。在你实际编写使用模板方法的代码之前,没有什么可以编译的,所以如果你使用的是不太智能的编译器,你可能看不到任何错误。

你甚至可以定义栏是这样的:

template <class T> 
void bar(T t) 
{ 
    foo(t); 
    snarf(); 
    snorf(); 
    divideByZero(); 
    asdf--+|&* 
} 

而且它仍将编译(有一些编译器),只要你没有尝试过用吧。

+0

看来CLang ++ 3.3仍然没有找到错误,即使主要调用它。 – bennofs

+0

当类似于上面的代码实际实例化时,g ++和clang ++都无法找到错误。 – Azoth