Clang 6中临时对象的模板实参推导异常问题问询
Clang 6 中类模板实参推导(CTAD)的临时对象构造Bug
这确实是 Clang 6.x 版本的已知编译器实现缺陷,属于对C++17类模板实参推导(CTAD)支持不完整的情况。
问题原因
虽然 Clang 官方状态页面显示自 Clang 5 起已实现 CTAD(对应提案 P0091R3、P0512R0),但在处理无命名临时对象的直接列表初始化(也就是你代码里的Print{1,"foo"s,2};这一行)时,编译器无法正确触发模板实参推导逻辑。而其他写法(显式指定模板参数、用auto推导变量、或者直接声明变量的列表初始化)能正常工作,说明 CTAD 的实现仅在部分场景下生效,存在场景覆盖的遗漏。
解决方法
- 优先升级编译器:这是最彻底且无需修改代码的解决方案。Clang 7 及以上版本已经修复了这个 CTAD 的实现缺陷,升级后你的代码可以直接正常编译运行,无论使用
-std=c++17还是-std=c++2a编译选项。 - 若必须使用 Clang 6:很遗憾没有专门的编译标志能绕过这个缺陷。不过如果你暂时无法升级编译器,只能通过调整代码写法来规避(但这属于修改代码的范畴),比如改用你代码中已经验证可行的写法:
- 显式指定模板参数:
Print<int,string,int>{1,"foo"s,2}; - 用
auto接收临时对象:auto p1 = Print{1,"foo"s,2}; - 声明变量时初始化:
Print p2{1,"foo"s,2};
- 显式指定模板参数:
你的示例代码(格式化后)
#include <iostream> #include <string> using namespace std; template<class ...Ts> void print(Ts...ts){ (( cout << ... << ts )); } template<class ...Ts> struct Print { Print(Ts...ts){ (( cout << ... << ts )); } }; int main(){ Print{1,"foo"s,2}; /********** Broken in Clang **********/ Print<int,string,int>{1,"foo"s,2}; auto p1 = Print{1,"foo"s,2}; Print p2{1,"foo"s,2}; print(1,"foo"s,2); }
内容的提问来源于stack exchange,提问作者user9816683
相关产品推荐
相关产品推荐

