GCC / C ++ 17中带有模板模板类的问题


10

考虑以下2个重载

template<typename T>
bool test() {
    return true;
}

template<template<typename ...> class T>
bool test() {
    return false;
}

第一个适用于常规类,而第二个适用于未实例化的模板。例如:

    std::cout<<test<int>()<<std::endl; <-- this yields 1
    std::cout<<test<std::list>()<<std::endl; <--this yields 0

现在考虑以下模板函数:

template<typename U>
bool templfun(){
    struct A{
        bool f(){
            return test<A>(); // <-- this gives an error
        }
    };
    return test<A>();  // <-- this is ok
}

在GCC中,当Clang编译时,它为模棱两可的重载解决方案给出了错误。有趣的是,第二次调用test()不会产生错误(即使在GCC中也是如此)。而且,如果我删除template<typename U>templfun顶部的东西,gcc会停止抱怨。

这是GCC的错误还是非法代码?

Answers:


4

GCC是错误的;struct A模板实体,但显然不是模板(因为它不是以template关键字开头),因此没有歧义。

为了确认,我们可以重命名type参数,以查看G ++尝试使用template-template重载。

template <typename X>
bool test() {
    return true;
}

template <template <typename...> class Y>
bool test() {
    return false;
}

template <typename U>
bool templfun() {
    struct A {
        bool f() {
            return test<A>(); // <-- this gives an error
        }
    };
    return test<A>(); // <-- this is ok
}

bool run() {
    return templfun<int>();
}

G ++输出:(链接到Godbolt

<source>:15:27: error: call of overloaded 'test<templfun() [with U = int]::A>()' is ambiguous
   15 |             return test<A>(); // <-- this gives an error
      |                    ~~~~~~~^~

<source>:2:6: note: candidate: 'bool test() [with X = templfun() [with U = int]::A]'
    2 | bool test() {
      |      ^~~~

<source>:7:6: note: candidate: 'bool test() [with Y = templfun()::A]'
    7 | bool test() {
      |      ^~~~

显然“ candidate: 'bool test() [with Y = templfun()::A]'”是伪造的。

请注意,在C ++ 11之前,不允许将本地类型作为模板参数(请参阅C ++ 03§14.3.1.2),因此可以解释G ++实现的复杂性。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.