C++ 1y/C++ 14 N3690によると、可変テンプレートの特殊化のタイプは、プライマリテンプレートのタイプと同じである必要がありますか?
template<int x>
char y = f(x);
template<>
double y<42> = g();
もしそうなら、どういうわけかプライマリを未定義のままにすることは可能ですか?
template<int x>
???? y = ???; // undefined
template<>
double y<42> = g();
これはドラフトのどこでカバーされていますか?
クラステンプレートの同等の機能は次のとおりです。
template<int x>
struct S
{
static char y;
};
template<>
struct S<42>
{
static double y;
};
そして
template<int x>
struct S; // undefined
template<>
struct S<42>
{
static double y;
};
変数テンプレートの特殊化のタイプはプライマリテンプレートのタイプと同じである必要がありますか?
いいえ、変数テンプレートの明示的(または部分的)特殊化は、暗黙的なインスタンス化によって暗示されるタイプとは異なるタイプを指定できます。 Clangの機能を実装したところ、この場合、仕様に型の一致を要求するルールがないことがわかり、この問題をC++コアワーキンググループに持ち込み、この省略が意図的なものであることが確認されました。
どういうわけかプライマリを未定義のままにすることは可能ですか?
タイプで指定せずにプライマリ変数テンプレートを宣言することはできません-そのようなことを可能にする構文はありません。
これはドラフトのどこでカバーされていますか?
これらは両方とも省略でカバーされています-型を一致させる必要があるルールはなく、型なしで変数テンプレートを宣言するための構文もありません。したがって、標準の特定の部分を指摘して、「ここにルールがない」と言うことはできません。
C++標準委員会のリフレクターにアクセスできる場合は、これについての説明について、core-23901で始まるスレッドを参照してください。
以下はclangtrunk-std=c++1y
でコンパイルします:
#include <iostream>
template<int x>
char y = 3;
template<>
double y<42> = 2.5;
char c {y<17>};
double d {y<42>};
したがって、変数テンプレートの特殊化は、そのプライマリと同じタイプである必要はないか、clangにN3690のバグのある実装があります。
特殊化の宣言は、タイプを含め、プライマリテンプレートと正確に一致する必要があることを完全に期待しています。これは、可変テンプレートにとって新しいことではありません。私はまだ標準の詳細を追跡していませんが、それがこの詳細をどこで指定しているかを確認します。
以下のコードは、あなたが望むものに似た何かをしているようです。つまり、変数タイプを開いたままにしておきます。
#include <iostream>
template <int X> struct var_type { typedef int type; };
template <> struct var_type<42> { typedef double type; };
int f(int x) { return x; }
double g() { return 3.14; }
template <int X>
typename var_type<X>::type var = f(X);
template <>
typename var_type<42>::type var<42> = g();
int main()
{
std::cout << "var<17>=" << var<17> << '\n';
std::cout << "var<42>=" << var<42> << '\n';
}
Clangが標準化を目的とした機能を表現していると推定するのは少し危険です。 (注:この回答については何も言及していません。)
もちろん、タイプの変更を許可することのフォールアウトは、何らかの方法で参照された後にテンプレートを特殊化できないことですが、他のすべての種類のテンプレートの場合、カットオフ時間はODRで使用されます。彼らが何か風変わりなことを計画していない限り、これはClangのバグのように見えます。
いつでも型テンプレートを使用して、変数テンプレートの型を宣言できます。
template< typename t >
struct x_type { typedef … type; };
template< typename t >
typename x_type< t >::type x = …;
今x_type
は専門的かもしれません。これは、Clangが現在バグがある可能性を防ぐだけです。タイプが不確定なオブジェクトを参照することはできません。 C++はそれをサポートしていません。オブジェクトODRの参照-クラステンプレートの特殊化を使用します。