std::convertible_to无法识别显式转换类型的技术咨询
问题与解答
疑问1:std::convertible_to与显式转换运算符的矛盾
根据cppreference对std::convertible_to的定义,该概念要求与std::declval()类型、值类别一致的表达式可隐式和显式转换为To类型,且两种转换等价。我原本以为如果类U拥有explicit operator V()成员,std::convertible_to<U, V>应该成立,但在MSVC v19中,以下代码的static_assert编译失败:
#include <concepts> #include <iostream> class ExplictClass { public: inline explicit operator int() const { return 5; } }; int main() { static_assert(std::convertible_to<ExplictClass, int>, "Explicit not convertible?"); }
这是我对概念理解错了、代码有问题、文档错误还是MSVC的兼容性问题?
需求:实现特定逻辑的to_string函数模板
我需要实现一个to_string模板,要求:
const char*、char*以及拥有explicit operator std::string的类型(比如上面的ExplictClass)使用特化版本- 其他类型使用通用的ostringstream版本
当前尝试的代码如下:
#include <sstream> #include <string> template<class T> std::string to_string(T val) { std::ostringstream stream; stream << val; return stream.str(); } template<Convertible<std::string> T> std::string to_string(T val) { return static_cast<std::string>(val); }
解答
关于std::convertible_to的理解错误
你对std::convertible_to的概念理解有误,这个概念的核心要求是存在合法的隐式转换,而非仅支持显式转换。cppreference的描述里,"可隐式和显式转换"是指:当隐式转换存在时,显式转换必然也存在且结果等价——反过来,只有显式转换的情况并不满足该概念。
具体来说,std::convertible_to<U, V>的标准定义等价于:
static_cast<V>(std::declval<U>())合法(支持显式转换)- 同时,隐式转换也合法(比如
V v = std::declval<U>();能通过编译) - 两种转换的结果等价
当类使用explicit修饰转换运算符时,隐式转换被禁止,因此std::convertible_to概念不成立。MSVC的行为是符合C++标准的,不存在兼容性问题。
实现符合需求的to_string模板
要覆盖带显式std::string转换运算符的类型,你需要自定义一个概念,只要能通过static_cast转换为std::string即可:
#include <concepts> #include <sstream> #include <string> template<typename T> concept StringConvertible = requires(T t) { static_cast<std::string>(t); }; // 通用版本:处理无法直接static_cast到string的类型 template<class T> std::string to_string(T val) { std::ostringstream stream; stream << val; return stream.str(); } // 特化版本:匹配所有可static_cast到string的类型 template<StringConvertible T> std::string to_string(T val) { return static_cast<std::string>(val); }
这个实现满足你的需求:
const char*、char*可以被static_cast<std::string>合法转换,会匹配特化版本- 拥有
explicit operator std::string()的类,通过static_cast可以完成转换,也会匹配特化版本 - 其他无法通过
static_cast转为std::string的类型,会调用通用的ostringstream版本
内容的提问来源于stack exchange,提问作者WARhead
相关产品推荐
相关产品推荐

