6

Understanding partial specialization of inherited nested class templates次のソースコードをからもたらされる継承された入れ子になったテンプレートクラスの特殊

#include <type_traits> 
struct Base 
{ 
    template<class U, class _ = void> struct Inner: std::true_type {}; 
    template<class _> struct Inner<char, _>: std::false_type {}; 
}; 
struct Derived : Base 
{ 
}; 

template<class _> struct Derived::Inner<int, _>: std::false_type {}; 

私は継承されたクラスを専門に関する問題を持っていたので、私はGoogleで検索し、上記の質問を見つけます。上記の質問のソースコードはgcc/clangの問題なしにコンパイルされましたが、msvcはコンパイルを拒否し、C2427を発行しました(https://msdn.microsoft.com/en-us/library/10het5hx.aspx参照)。

上記の状況(非テンプレートクラスのネストされたテンプレートクラスを特化する)は、https://msdn.microsoft.com/en-us/library/10het5hx.aspx(テンプレートクラスのネストされた非テンプレートクラスを定義する)とはかなり異なると私は考える。

msvcとgcc/clangのどちらが間違っていますか?それとも、この動作を指定するための標準が非常に不明ですか?

私はMSVCが間違っている願っています...

答えて

2

クランとGCCは間違っている、とMSVCおよびEDGはその部分的な特殊定義を拒否する権利があります。

部分的な特殊化自体はテンプレートであり、クラステンプレート定義はクラス定義(文法では、クラス指定子)の観点から構文的に構築されます。そのような定義の中で、Derived::Inner<int, _>クラスヘッド名であり、Derived::ネストされた名前指定子です。

[9p11]標準で述べている:

クラスヘッド名ネストされた名指定子が含まれている場合は、 クラス指定子そのクラスを指すものとします先に が、ネストされた名前指定子 が参照するクラスまたはネームスペースに直接、またはその 名前空間のインラインネームスペースセット(つまり、単に継承されたo rは 使用宣言によって導入されました)、およびクラス指定子は、前の宣言を囲む 名前空間に現れます。 [...]

したがって、Base::Inner<int, _>を使用する必要があります。コメントで述べたように


、上記の引用は(その文法の生産もクラスヘッド-名を使用して終わる)やクラステンプレートの明示的な特殊定義に適用されます。


以下はあなたの例には直接当てはまりませんが、私はそれに言及する価値があることを発見しました。上記の引用は、クラステンプレート(または明示的な特殊化)を指すこと

注定義ではなく、そのような

template<class _> struct Derived::Inner<int, _>; 
として宣言

構文的、struct Derived::Inner<int, _>段落詳述型指定子があるに上記は適用されません。だから、標準的な表現は技術的にそのような宣言を許す。

これは監督ではないようです:上記の文言は、コメントが含まれてDR284の決議により導入されました:感情は、これはクラス定義に必要とされなければならないということでした

、 けど詳細な型指定子ではありません(宣言ではなく 参照)。 [...]

提案解像度が詳述型指定子を含め、しかしそれらは最終的な文言から除去しました。

しかし、MSVCもEDGもこのような宣言を受け入れていません。 DRのコメントは、宣言ではない精巧型指定子のみを許可することを目的としていたようですが、これは文言に反映されていないようです(標準バグです)。

+0

これはあまりにも悪い...派生クラス名を使ってネストされたクラステンプレートを特化することができれば非常にいいです...とにかく、非常に有益な答えをありがとう!ところで、[9p11]は明示的な特殊化にも適用されますか?この例では、ダミーのパラメータを削除したときにmsvcがまだ拒否しているようです。 –

+0

@JunekeyJeonはい、それは、私が言うことができる限りです。 – bogdan

関連する問題