clang++与cl.exe对C++模板代码的处理差异问题咨询
报错原因
__is_assignable_no_precondition_check是MSVC专属编译器扩展:这是MSVC特有的内置类型检查原语,你使用的Clang 12.0.0没有实现对这个MSVC专属原语的支持,也不兼容MSVC允许直接将类型作为实参传入该内置原语的扩展语法。- Clang语法解析规则不兼容当前写法:标准C++语法不允许直接将类型作为函数实参传递,Clang解析到你把
add_lvalue_reference_t<_Ty>这类类型直接放在函数调用参数位置时,会误认为你要做函数式类型转换,因此抛出需要补充(的报错。
解决思路
方案1:替换为标准库等价实现(最推荐,跨编译器通用)
直接使用C++标准库的std::is_assignable_v替换MSVC专属原语,功能完全匹配,修改后的代码如下:#include <type_traits> using void_t = void; template <class Ty, class = void> struct Add_reference { using Lvalue = Ty; using Rvalue = Ty; }; template <class Ty> struct Add_reference<Ty, void_t<Ty&>> { using Lvalue = Ty&; using Rvalue = Ty&&; }; template <class Ty> using add_lvalue_reference_t = typename Add_reference<Ty>::Lvalue; template <class Ty> constexpr bool _Is_copy_assignable_unchecked_v = std::is_assignable_v< add_lvalue_reference_t<Ty>, add_lvalue_reference_t<const Ty> >;注意:原代码中
_Ty、_Add_reference这类下划线开头加大写字母的标识符属于C++标准保留给标准库实现的命名空间,用户自定义代码使用会触发未定义行为,建议修改命名规则。方案2:增加编译器分支兼容
如果需要保留MSVC下的原实现,可以通过宏判断编译器类型,不同编译器走不同实现:template <class _Ty> constexpr bool _Is_copy_assignable_unchecked_v = #ifdef _MSC_VER __is_assignable_no_precondition_check( add_lvalue_reference_t<_Ty>, add_lvalue_reference_t<const _Ty> ); #else std::is_assignable_v< add_lvalue_reference_t<_Ty>, add_lvalue_reference_t<const _Ty> >; #endif方案3:开启Clang的MSVC扩展兼容模式
编译时给Clang增加-fms-extensions参数,让Clang尝试兼容MSVC的扩展语法。但该方案依赖Clang版本对__is_assignable_no_precondition_check的实现支持,Clang 12.0.0版本对该原语的支持不完善,大概率还是会报错,仅作为临时尝试方案。
内容的提问来源于stack exchange,提问作者Software-security-is-not-free
相关产品推荐
相关产品推荐

