为什么C++中返回类型为std::string时会出错?

Min*_*inC 2 c++ struct return-type

我有一个枚举类和一个将枚举类值与字符串匹配的映射。

\n

例如,

\n
enum class FRUIT {\n    APPLE,\n    ORANGE,\n    MELON\n};\n\nstd::map<FRUIT, std::string> m {\n    {FRUIT::APPLE,  "3"},\n    {FRUIT::ORANGE, "SWEET"},\n    {FRUIT::MELON,  "24.5"}\n};\n
Run Code Online (Sandbox Code Playgroud)\n

还有一个类模板包装每个枚举类值的实际数据类型。

\n
template<FRUIT f>\nstruct Type {\n  using type=int;  \n};\ntemplate<> struct Type<FRUIT::ORANGE> {\n    using type=string;\n};\ntemplate<> struct Type<FRUIT::MELON> {\n    using type=double;\n};\n
Run Code Online (Sandbox Code Playgroud)\n

我尝试获取与每个枚举类值相对应的值,如下所示

\n
template<FRUIT f>\ntypename Type<f>::type getValue() {\n    \n    if (is_same<typename Type<f>::type, int>::value)\n        return std::stoi( m[f] );\n\n    else if (is_same<typename Type<f>::type, double>::value)\n        return std::stod( m[f] );\n\n    else if (is_same<typename Type<f>::type, string>::value)\n        return m[f];    \n}\n
Run Code Online (Sandbox Code Playgroud)\n

我不知道错误出在哪里。当调用 时getValue<FRUIT::APPLE>(),我认为满足第一个条件并因此std::stoi(m[f])返回,但它仍然Cannot convert \xe2\x80\x98std::map<...>::mapped_type\xe2\x80\x99 {aka \xe2\x80\x98std::__cxx11::basic_string\xe2\x80\x99} to \xe2\x80\x98Type::type\xe2\x80\x99 {aka \xe2\x80\x98int\xe2\x80\x99}在最后一行显示错误!

\n

如果没有std::string涉及,则去掉最后一个条件。一切都很好。

\n

jpa*_*cek 6

问题在于您正在区分运行时返回类型的方式,如下所示:

if (a)
   return expA;
if (b)
   return expB;
... etc
Run Code Online (Sandbox Code Playgroud)

在这种情况下,所有分支都必须是可编译的,并且必须返回可转换为返回类型的值。因此,例如,当FRUIT fFRUIT::APPLE时,所有分支都必须返回一个可转换为 的值int。但std::string事实并非如此,因此出现错误。

您可以通过以下任一方式解决:

  • 如果可以的话,使用if constexpr在编译时评估分支(C++17 及更高版本):
if constexpr (a)
   return expA;
... etc.
Run Code Online (Sandbox Code Playgroud)
  • 按照旧方法,根据需要返回的类型专门化一个函数,例如:
template <class T>
T convertValue(const std::string& s);

template <>
int convertValue<int>(const std::string& s)
{
  return std::stoi( s );
}

template <>
double convertValue<double>(const std::string& s)
{
  return std::stod( s );
}

template <>
std::string convertValue<std::string>(const std::string& s)
{
  return s;
}
Run Code Online (Sandbox Code Playgroud)

然后你的getValue()函数就变得简单了:

template<FRUIT f>
typename Type<f>::type getValue() {
   return convertValue<typename Type<f>::type>(m[f]);
}
Run Code Online (Sandbox Code Playgroud)