Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is template qualifier required in class template non-dependent member variables?

I got the compile error "error: use 'template' keyword to treat 'foo' as a dependent template name" when I compile the following code on commented line. (test4)

All other parts of codes are successfully compiled.

#include <tuple>

struct my {
    template <typename T>
    void foo() {}
};

void test1() {
    my m;
    auto tr = std::forward_as_tuple(m);
    auto& t0 = std::get<0>(tr);
    t0.foo<int>();
}

template <typename T>
struct test2 {
    void method() {
        my m;
        auto tr = std::forward_as_tuple(m);
        auto& t0 = std::get<0>(tr);
        t0.foo<int>();
    }
};

template <typename T>
struct test3 {
    void method() {
        m.foo<int>();
    }
    my m;
};

template <typename T>
struct test4 {
    void method() {
        auto tr = std::forward_as_tuple(m);
        auto& t0 = std::get<0>(tr);
        t0.foo<int>();          // error: use 'template' keyword to treat 'foo' as a dependent template name
        t0.template foo<int>(); // OK
    }
    my m;
};

template <typename T>
struct test5 {
    void method() {
        std::tuple<my> tr = std::forward_as_tuple(m);
        auto& t0 = std::get<0>(tr);
        t0.foo<int>();
    }
    my m;
};

template <typename T>
struct test6 {
    void method() {
        auto tr = std::forward_as_tuple(m);
        my& t0 = std::get<0>(tr);
        t0.foo<int>();
    }
    my m;
};


int main() {
    test1();
    test2<int>().method();
    test3<int>().method();
    test4<int>().method();
    test5<int>().method();
    test6<int>().method();
}

test4 is a class template but m is non dependent type.

I tried to compile gcc and clang. gcc 7.1.0 dosen't report errors, but clang 4.0 and later report the compile error.

Error

https://wandbox.org/permlink/HTSBJMD2kXwfWObl (clang 4.0) https://wandbox.org/permlink/BcUT8gtaFxwC41c5 (clang HEAD)

No error

https://wandbox.org/permlink/GjIvZa3i5HB8uh6w (gcc 7.1.0)

Which is correct behavior?

like image 383
Takatoshi Kondo Avatar asked Jun 29 '17 05:06

Takatoshi Kondo


1 Answers

I'm going to agree with your suspicion. This is indeed a clang bug.

The template is required if and only if t0 is a dependent name. In particular, it's required if t0 depends on T. And that's the T in test4<T>.

Now, t0 depends on my m, and there's a my::foo<T>, but that's an unrelated T in a different scope. Additionally, t0 doesn't depend on my::foo<T>.

like image 134
MSalters Avatar answered Oct 13 '22 01:10

MSalters