C++模板类型别名能否省略空尖括号?编译错误解析
示例代码
#include <type_traits> template<bool condition> struct X { template<std::enable_if_t<condition, bool> = true> using MaybeInt = int; template<std::enable_if_t<condition, bool> = true> static MaybeInt<> MaybeResult() { return 0; } }; int main() { return X<true>::MaybeResult(); }
问题1:使用X<true>::MaybeInt类型时,能否省略末尾的空尖括号?
不能省略。
原因:MaybeInt是模板别名(alias template),本质上还是一个模板,而非直接定义好的具体类型。哪怕它的模板参数带有默认值,要把它当成具体类型使用时,必须显式提供模板参数(这里用空尖括号<>表示使用默认参数)来完成模板实例化。直接写X<true>::MaybeInt的话,编译器只会识别它为一个模板本身,而非实例后的int类型,无法作为类型使用。
问题2:移除第9行的空尖括号后,为何编译报错?
移除空尖括号后的代码片段:
template<std::enable_if_t<condition, bool> = true> static MaybeInt MaybeResult() { return 0; }
clang在C17环境下的报错信息:
main.cpp:9:12: error: use of alias template 'MaybeInt' requires template arguments; argument deduction not allowed in function return type
static MaybeInt MaybeResult() {
^~~~~~~~
main.cpp:6:5: note: template is declared here
using MaybeInt = int;
^
1 error generated.
错误原因:函数返回类型的上下文不支持模板参数推导。虽然MaybeInt的模板参数有默认值,但C++标准明确规定,在函数返回类型这个位置,编译器不会自动尝试用默认参数去实例化模板别名,也不会进行模板参数推导。你必须显式写出<>,明确告知编译器“使用默认参数来实例化这个模板别名”。这样规定是为了避免返回类型出现歧义,同时保证模板使用的显式性,防止隐式推导带来的意外行为。
内容的提问来源于stack exchange,提问作者James Farrell

