已删除 "general" 大小写的专用模板函数无法使用 g++ <=4.8.0 和 clang++ 进行编译
Specialized template function with deleted "general" case fails to compile with g++ <=4.8.0 and clang++
用老版本的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 中仍然不起作用)
我不知道以下内容是否有启发性,但我发现 defect report 941: Explicit specialization of deleted function template 的状态为 C++11,其中说明了以下内容 (强调我的):
According to 14.7.3 [temp.expl.spec] paragraph 1, only non-deleted
function templates may be explicitly specialized. There doesn't
appear to be a compelling need for this restriction, however, and it
could be useful to forbid use of implicitly-instantiated
specializations while still allowing use of explicitly-specialized
versions.
Proposed resolution (February, 2010):
Change 14.7.3 [temp.expl.spec] paragraph 1 as follows:
An explicit specialization of any of the following:
non-deleted function template
class template
non-deleted member function of a class template
static data member of a class template
member class of a class template
member class template of a class or class template
non-deleted member function template of a class or class
template
can be declared...
现在标准草案 N4527 的当前状态是 14.7.3 显式专业化 [temp.expl.spec]:
1 An explicit specialization of any of the following:
(1.1) — function template
(1.2) — class template
(1.3) — variable template
(1.4) — member function of a class template
(1.5) — static data member of a class template
(1.6) — member class of a class template
(1.7) — member enumeration of a class template
(1.8) — member class template of a class or class template
(1.9) — member function template of a class or class template
...
所以我猜:
template<typename T>
void foo() = delete;
template<>
void foo<int>(){}
int main() {
foo<int>();
return 0;
}
是 C++11 标准兼容代码,应该被接受。
用老版本的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 中仍然不起作用)
我不知道以下内容是否有启发性,但我发现 defect report 941: Explicit specialization of deleted function template 的状态为 C++11,其中说明了以下内容 (强调我的):
According to 14.7.3 [temp.expl.spec] paragraph 1, only non-deleted function templates may be explicitly specialized. There doesn't appear to be a compelling need for this restriction, however, and it could be useful to forbid use of implicitly-instantiated specializations while still allowing use of explicitly-specialized versions.
Proposed resolution (February, 2010):
Change 14.7.3 [temp.expl.spec] paragraph 1 as follows:
An explicit specialization of any of the following:
non-deletedfunction templateclass template
non-deletedmember function of a class templatestatic data member of a class template
member class of a class template
member class template of a class or class template
non-deletedmember function template of a class or class templatecan be declared...
现在标准草案 N4527 的当前状态是 14.7.3 显式专业化 [temp.expl.spec]:
1 An explicit specialization of any of the following:
(1.1) — function template
(1.2) — class template
(1.3) — variable template
(1.4) — member function of a class template
(1.5) — static data member of a class template
(1.6) — member class of a class template
(1.7) — member enumeration of a class template
(1.8) — member class template of a class or class template
(1.9) — member function template of a class or class template
...
所以我猜:
template<typename T>
void foo() = delete;
template<>
void foo<int>(){}
int main() {
foo<int>();
return 0;
}
是 C++11 标准兼容代码,应该被接受。