4

I have the following minified code.
The line with // Only VS compiles on VS but not on clang,
And the line with // Only clang compiles on clang but not on VS.
Who is correct? More importantly, how to make an equivalent line compile on both?
The versions tested are clang 3.7.0, and VS 2015.

#include <functional>
#include <tuple>

template<typename... Args>
class C
{
    struct B
    {
        std::function<void(Args...)> func;
        B(std::function<void(Args...)> func) : func(func) { }
    };
    template<typename T>
    struct D : B
    {
        using B::B;
        template<size_t... I>
        void Call(T &t, std::index_sequence<I...>)
        {
            func(std::get<I>(t)...); // Only VS
            B::template func(std::get<I>(t)...); // Only clang
        }
    };
    D<std::tuple<Args...>> d;
public:
    C(std::function<void(Args...)> func) : d(func) { }
    void Call()
    {
        std::tuple<Args...> t;
        d.Call(t, std::make_index_sequence<sizeof...(Args)>());
    }
};

void f(int)
{

}

int main()
{
    C<int> c(f);
    c.Call();
}
Piotr Skotnicki
  • 46,953
  • 7
  • 118
  • 160
Daniel
  • 30,896
  • 18
  • 85
  • 139

1 Answers1

4

I think both are wrong. For the first use func(...) is an unqualified name looked up using argument dependent look-up which doesn't find a function in a base class. The use of B::template func(...) uses an excess keyword template. You can force look-up of func in the context of the class using

this->func(...);

The this-> forces the necessary context. I think, B::func(...) should also work but I'm using this->func(...) in similar situations.

I think the relevant clause is 14.6.2 [temp.dep] paragraph 3:

In the definition of a class or class template, the scope of a dependent base class (14.6.2.1) is not examined during unqualified name lookup either at the point of definition of the class template or member or during an instantiation of the class template or member.

The issue is that B is dependent on the template arguments of the enclosing class. Qualifying the name with this-> or the base class name force look-up in the base class context.

Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380
  • Before argument dependent lookup, it should lookup `func` as if it was a member in the base class and find it. – Daniel May 28 '16 at 22:12
  • 4
    Nope, not for class templates. Class templates generally don't look things up in their base classes unless look-up in the base is forced by some form of qualification (`B::` or `this->`). – Dietmar Kühl May 28 '16 at 22:14