19

古いバージョンの g++ (4.8.0、MinGW) でプロジェクトをコンパイルすると、次のコードがコンパイルに失敗することがわかりました。

template<typename T>
void foo() = delete;

template<>
void foo<int>(){}

int main() {
    foo<int>();
    return 0;
}

基本ケースが削除されていることがわかった場合、g++ は明示的な特殊化を探そうとさえしないようです。

mitalia@mitalia:~/scratch$ /opt/mingw32-dw2/bin/i686-w64-mingw32-g++ -std=c++11 buggy_deleted_template.cpp 
buggy_deleted_template.cpp: In function 'int main()':
buggy_deleted_template.cpp:8:14: error: use of deleted function 'void foo() [with T = int]'
     foo<int>();
              ^
buggy_deleted_template.cpp:5:6: error: declared here
 void foo<int>(){}
      ^
mitalia@mitalia:~/scratch$ /opt/mingw32-dw2/bin/i686-w64-mingw32-g++ --version 
i686-w64-mingw32-g++ (rubenvb-4.8.0) 4.8.0
Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

代わりに、g++ 4.8.4 および 5.2 (Linux 上) は文句を言いません。これは古いバージョンのコンパイラのバグですか、それとも標準の灰色の領域ですか?


補遺

clang 3.4.1 も気に入らないようです:

mitalia@mitalia:~/scratch$ clang++ -std=c++11 buggy_deleted_template.cpp                                                             
buggy_deleted_template.cpp:5:6: error: redefinition of 'foo'                                                                         
void foo<int>(){}
     ^
buggy_deleted_template.cpp:5:6: note: previous definition is here
buggy_deleted_template.cpp:8:5: error: no matching function for call to 'foo'
    foo<int>();
    ^~~~~~~~
buggy_deleted_template.cpp:2:6: note: candidate template ignored: substitution failure [with T = int]
void foo() = delete;
     ^
2 errors generated.
mitalia@mitalia:~/scratch$ clang++ --version
Ubuntu clang version 3.4-1ubuntu3 (tags/RELEASE_34/final) (based on LLVM 3.4)
Target: x86_64-pc-linux-gnu
Thread model: posix

(そして、コメントの@Baum mit Augenは、3.7ではまだ機能しないと報告しています)

4

1 に答える 1

11

以下が啓発的かどうかはわかりませんが、欠陥レポート 941: Explicit specialization of deleted function template with status C ++11 を見つけました。

14.7.3 [temp.expl.spec] パラグラフ 1 によると、削除されていない関数テンプレートのみを明示的に特殊化できます。ただし、この制限にやむを得ない必要性はないようです。明示的に特殊化されたバージョンの使用を許可しながら、暗黙的にインスタンス化された特殊化の使用を禁止すると便利な場合があります。

決議案 (2010 年 2 月):

14.7.3 [temp.expl.spec] パラグラフ 1 を次のように変更します。

次のいずれかの明示的な特殊化:

削除されていない関数テンプレート

クラス テンプレート

削除されていないクラス テンプレートのメンバ関数

クラス テンプレートの静的データ メンバー

クラス テンプレートのメンバ クラス

クラスまたはクラス テンプレートのメンバ クラス テンプレート

削除されていないクラスまたはクラス テンプレートのメンバ関数テンプレート

宣言できる…

現在、ドラフト標準N4527の現在の状態は14.7.3 明示的特殊化 [temp.expl.spec] です。

1 次のいずれかの明示的な特殊化:

(1.1) — 関数テンプレート

(1.2) — クラステンプレート

(1.3) — 変数テンプレート

(1.4) — クラステンプレートのメンバー関数

(1.5) — クラス テンプレートの静的データ メンバー

(1.6) — クラステンプレートのメンバークラス

(1.7) — クラステンプレートのメンバー列挙

(1.8) — クラスまたはクラス テンプレートのメンバ クラス テンプレート

(1.9) — クラスまたはクラス テンプレートのメンバ関数テンプレート

...

だから私は推測します:

template<typename T>
void foo() = delete;

template<>
void foo<int>(){}

int main() {
    foo<int>();
    return 0;
}

C++11 標準互換コードであり、受け入れられる必要があります。

于 2015-10-21T11:33:42.183 に答える