MSVC报显式转换歧义而GCC/Clang无错,谁合规?及类型特性疑问
问题解答
1. 哪个编译器行为符合C++标准?
你的String类同时提供了operator std::string()和operator const char*()两个转换函数,当执行static_cast<std::string>(s)时,编译器需要评估两条可能的转换路径:
- 路径1:直接调用
operator std::string()完成转换,这是单步用户定义转换序列。 - 路径2:先调用
operator const char*()得到const char*,再通过std::string的构造函数完成转换,这是两步用户定义转换序列(用户定义转const char*+ 用户定义转std::string)。
根据C++标准的转换序列规则:包含更少用户定义转换步骤的序列优先级更高。因此路径1是更优选择,编译器应当直接选择operator std::string(),不会产生歧义。
GCC与Clang的行为符合标准,MSVC错误地判定两条路径存在歧义,属于编译器实现问题。
2. 检测显式转换可行性的类型特性
标准库中没有直接命名为is_explicitly_convertible或is_static_castible的特性,但可以通过SFINAE自行实现一个检测static_cast合法性的特性:
#include <type_traits> #include <utility> template<typename To, typename From> struct is_static_castible { private: // 尝试执行static_cast,若合法则返回true_type template<typename T, typename F> static auto test(int) -> decltype(static_cast<T>(std::declval<F>()), std::true_type{}); // 匹配失败时返回false_type template<typename, typename> static std::false_type test(...); public: static constexpr bool value = decltype(test<To, From>(0))::value; }; template<typename To, typename From> constexpr bool is_static_castible_v = is_static_castible<To, From>::value;
这个特性可以检测任意类型间是否能通过static_cast完成转换,包括使用explicit标记的转换函数或构造函数的场景。
另外,C++20引入的std::constructible_from可以检测是否能通过构造函数(包括explicit构造函数)构造目标类型,但仅针对构造函数的情况,无法覆盖类类型的转换函数场景,因此上述自定义特性适用性更广。
内容的提问来源于stack exchange,提问作者joergbrech
相关产品推荐
相关产品推荐

