clang と gcc の両方がこのコードを拒否します。
template<int i>
struct ambiguous
{
static const int value = i;
};
namespace N
{
template<int i>
void ambiguous();
int i = ambiguous<3>::value; // finds the function template name
}
ただし、どちらも次のコードを受け入れます。
struct ambiguous
{
static const int value = 0;
};
namespace N
{
void ambiguous();
int i = ambiguous::value;
}
標準では、名前の前の名前のルックアップは、::
「特殊化が型である名前空間、型、およびテンプレートのみを考慮する」と述べています。このコードを拒否するのにclangとgccは正しいですか? もしそうなら、私は何が欠けていますか?
C++ Working Draft Standard n3337 から
3.4.3 修飾名検索 [basic.lookup.qual]
クラスまたは名前空間のメンバーまたは列挙子の名前は、そのクラス、名前空間、または列挙を示す入れ子になった名前指定子に :: スコープ解決演算子 (5.1) を適用した後に参照できます。nested-name-specifier 内の :: スコープ解決演算子の前に decltype-specifier がない場合、 :: の前にある名前の検索では、特殊化が types である名前空間、型、およびテンプレートのみが考慮されます。見つかった名前が名前空間、クラス、列挙、または依存型を指定していない場合、プログラムは不適切な形式です。
14.2 テンプレートの特殊化の名前 [temp.names]
template-name がテンプレート引数によって明示的に修飾されるためには、その名前が template を参照するために知られている必要があります。
名前ルックアップ (3.4) の後、名前がテンプレート名であるか、operator-function-id またはliteral-operator-id がオーバーロードされた関数のセットを参照しており、そのメンバーのいずれかが関数テンプレートである場合、これが続く場合a の
<
場合、 the<
は常に template-argument-list の区切り文字として使用され、小なり演算子として使用されることはありません。
編集
式と宣言の間のあいまいさとこの問題の混同を避けるために、非型パラメーターの代わりに型パラメーターを使用するテンプレートを使用した元のコードを次に示します。
template<class>
struct ambiguous
{
static const int value = 0;
};
namespace N
{
template<class>
void ambiguous();
int i = ambiguous<int>::value; // finds the function template name
}
これにより、すべての場合で同じエラーが発生します。は<
演算子として解釈できません。
ambiguous
は明確にテンプレート名ですが、型または関数のいずれかである可能性があります。関数または型のどちらに名前を付けるかを知らなくても、テンプレート ID 全体を解析し、後であいまいさを解決することができます。標準は、実装者がこれを行うことを許していますか?