3

I'm working on a project where SFINAE is used to detect whether a member function exists. I'm running into a problem with the following example:

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
    }
};

The problem seems to be that the access control (e.g. private) in the base class is not being respected in the derived class when trying to access inherited functions. Both foo and snarf should be inaccessible from the derived class. So when I try to test if some derived class has some function, it is incorrectly accessing the base class to find a match.

In g++ 4.8.1, both calling foo and snarf are incorrectly allowed to happen, which I'm pretty sure is an instance of this bug: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=41437

In clang++ 3.3, calling snarf is correctly identified as an error, but foo is allowed to be called, which seems like it should also be an error. Does this look like a bug in clang++? (I've posted a bug report just in case it turns out to be http://llvm.org/bugs/show_bug.cgi?id=16410)

Given that this may well be a bug in both compilers, is there any clever workaround I can use to detect that derived doesn't really have access to foo? The way I'm actually using this is the following:

template <class T, class T2, class Unused = void>
struct has_member_foo : std::false_type {};

Where has_member_foo is specialized to extend from std::true_type when calling declval<T&>().foo(declval<T2&>()) resolves to a valid function ala Checking a member exists, possibly in a base class, C++11 version. I need this to fail when a derived class inherits a private version of foo.

Community
  • 1
  • 1
Azoth
  • 1,652
  • 16
  • 24

1 Answers1

0

What does the compiler say when you write code that attempts to call bar?

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

If it displays an error there, then I think things are working as expected. Until you actually write code which uses a template method, there is nothing to compile, so you may not see any errors coming from it if you are using a less intelligent compiler.

You could even define bar like this:

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

And it will still compile (with some compilers), as long as you never try to use bar.

Taylor Brandstetter
  • 3,523
  • 15
  • 24
  • It seems that CLang++ 3.3 still doesn't find the error, even when main calls it. – bennofs Jun 21 '13 at 20:05
  • Both g++ and clang++ will fail to find the error when code similar to the above is actually instantiated. – Azoth Jun 21 '13 at 20:42