【问题标题】:Converting any type to any type将任何类型转换为任何类型
【发布时间】:2018-02-15 16:24:56
【问题描述】:

我想要一个函数模板来实现任意类型转换:

template<typename T, typename S>
S Convert(const T& input)
{
  // code.....
}

例如:

Convert<int, std::string>(12); // convert int to std::string
Convert<std::string, CString>("test"); // convert std::string to CString
Convert<bool, int>(true); // convert bool to int

有可能吗?

【问题讨论】:

  • 是的。 boost::lexical_cast 会这样做,虽然不是针对 CString,但肯定有自定义点。
  • @Quentin 我不想使用 boost
  • 这是你的电话,但这意味着是的,这是可能的,如果你想编写自己的代码,你可以从 Boost 的源代码中获得灵感。
  • @Quentin 好的,坦克
  • 不清楚你想要什么。 Convert 应该意思是什么?对于某些类型,有多种方法可以将T 转换为S,这些方法在不同的上下文中都可能有用。这就是为什么 C++ 有许多具有不同语义的转换运算符,以及为什么可以使用不同的配置选项以多种不同的方式将整数格式化为字符串的原因。如果问题是公正的,我是否可以制作具有任意语义和特殊行为情况的模板函数,那么答案是肯定的。

标签: c++ c++11 templates type-conversion


【解决方案1】:

您可以从以下主要功能模板开始:

template<typename T, typename S>
S Convert(const T& input) {
    return static_cast<S>(input);
}

这适用于将bool 转换为int。但是,对于其他更详细的转换,您需要针对所涉及的类型完全专门化该模板。是你必须定义相应转换的语义。

例如,将int 转换为std::string 的特化可以是:

template<>
std::string Convert<int, std::string>(const int& input) {
    return std::to_string(input);
}

std::string 转换为CString 的专业化可能是:

template<>
CString Convert<std::string, CString>(const std::string& input) {
   return CString(input.c_str());
}

后续实施

对于更安全的函数,请考虑上面的定义(阅读this comment)。请注意,模板参数的顺序是根据 OP 的问题交换的。

// (0) primary function template
template<typename TDst, typename TSrc>
TDst Convert(const TSrc& input) {
    return static_cast<TDst>(input);
}

// (1) specialization for converting int to string
template<>
std::string Convert<std::string, int>(const int& input) {
    return std::to_string(input);
}

// (2) overload for necessary std::string
template<typename TDst = CString>
TDst Convert(std::string& str) {
    return str.c_str();
}

// (3) overload for literal strings
template<typename TDst = CString>
TDst Convert(const char *cstr) {
    return cstr;
}

这样:

Convert<int>(true); // (0)

Convert<std::string>(12); // (1)

std::string str("foo");
Convert<CString>(str); // (2)

Convert<CString>("foo"); // (3)

Convert<CString, std::string>("foo"); // <-- compile error

【讨论】:

  • static_cast 无法将 std::string 转换为 CString
  • @JackD 你必须提供一个将std::string 转换为CString 的特化。我已经编辑了答案。
  • 这个 std::stringCString 函数似乎有些不安全,至少在我看来,创建无效指针似乎很容易:const char * ptr = Convert&lt;std::string, Cstring&gt;("foobar"); // Ouch 如果你真的要使用它,你可能会想让 T 类型成为第二个模板参数,而不是第一个,并且总是从上下文中推导出来而不是明确指定
  • @ChrisBeck 对不起,我不明白这一点。如果CString 确实隐式转换为const char *,那么我们仍然可以执行const char * ptr = Convert&lt;std::string, CString&gt;(str);(作为str 一个std::string 对象)并且会出现同样的问题。我想说实际的问题是CString 转换为指向即将被销毁的对象中包含的字符串的指针。我错过了什么?
  • 我想要的是(1)我在我的代码中写Convert&lt;Cstring&gt;("foobar"),而不是(2)编译器将其推断为Convert&lt;Cstring, Cstring&gt;("foobar"),并编译为无操作函数调用,这是安全的,因为我们只是返回指向字符串文字的指针。如果有人明确指定了两个模板参数,而不是让编译器推断输入类型,则不需要 (3) 时不涉及 std::stringConvert&lt;std::string,CString&gt;("foobar"),它被认为是一个错误,很容易被发现
猜你喜欢
  • 1970-01-01
  • 2021-11-07
  • 2023-03-17
  • 1970-01-01
  • 1970-01-01
  • 2019-07-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多