テンプレートテンプレートクラスでのGCC / C ++ 17の問題


10

次の2つのオーバーロードを検討してください

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

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

1つ目は通常のクラスで機能し、2つ目はインスタンス化されていないテンプレートで機能します。例えば:

    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()への2回目の呼び出しではエラーが発生しません(GCCでも)。さらに、template<typename U>templfunの上にあるものを削除すると、gccは文句を言うのをやめます。

これはGCCのバグですか、それとも違法なコードですか?

回答:


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 ++実装の複雑さを説明できることに注意してください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.