12

次の例を検討してください。

struct B { operator int(); };

template<class T>
struct X:B
{
    using B::operator T;
};

GCCはコードを受け入れますが、Clangと MSVC はコードを拒否します。どちらが正しい?

基本型が依存型の場合、すべてのコンパイラがコードを受け入れることに注意してください。

template<class T>
struct B { operator T(); };

template<class T>
struct X:B<T>
{
    using B<T>::operator T;
};
4

2 に答える 2

3

GCC は正しいと思います。§7.3.3/1 では、次のことがわかります。

using-declaration によって導入された一連の宣言は、using-declaration 内の名前に対して修飾名ルックアップ (3.4.3、10.2) を実行することによって検出されます。以下で説明するように非表示になっている関数は除外されます。

operator T実際、見つからない理由はわかりません。

template<class T>
struct X: B {
    T f () { return B::operator T; }
};

... g++ と clang で正常にコンパイルされます (MSVC ではテストしていません)。

以下を除いて、修飾名検索の変換関数に固有の標準には何も見つかりません。

変換関数用のメンバー テンプレートの特殊化は名前検索では見つからないため、using 宣言で変換関数が指定されている場合は考慮されません (14.5.2)。

ただしB::operator int、メンバー関数テンプレートの特殊化ではないため、上記では考慮しないでください。

于 2016-07-27T10:04:35.577 に答える
-1

うーん... Gccは最初のものも好きではありません。struct X以外のテンプレート パラメータで のインスタンスを作成しようとしない限り、コンパイルされますint。とはどういう意味X<double>::operator double()ですか? クラス B にはそのような演算子はありませんが、使用してみます。

要約すると、MSVC と clang は事前に警告しようとしますが (今は非常に愚かなことをしていなくても)、gcc は間違ったものを作成しようとした場合にのみエラーを生成します。これは gcc (5.3.0) ではコンパイルされません:

#include <iostream>

struct B { operator int(); };

template<class T>
struct X:B
{
    using B::operator T;
};

int main(int argc, char **argv)
{
    X<char> x;
    std::cout << "Hello!" << std::endl;
    return 0;
}
于 2016-07-27T09:58:21.527 に答える