【问题标题】:Accessing tuple value via scoped and typed enum fails通过作用域和类型化枚举访问元组值失败
【发布时间】:2015-11-15 18:53:56
【问题描述】:

当尝试通过范围和类型化枚举访问元组的值时,我收到一条错误消息,提示 std::get 没有匹配类型。

enum class User: std::size_t {
    FirstName = 1,
    LastName = 2,
};

std::tuple<std::string, std::string> user("Bobby", "Bean");

// Error
std::cout << std::get<User::FirstName>(user) << std::endl;

鉴于std::get 需要std::size_t 类型并且枚举的底层类型也是std::size_t,为什么会失败?

我知道我可以转换枚举的值,但我不确定为什么有必要这样做,因为这两种基础类型都是相同的。使用无范围的枚举,这工作得很好。

【问题讨论】:

  • 它是强类型的——你必须明确地转换它。见this
  • 这是一个有趣的问题,但请不要只说“错误”。将完整的错误消息放入问题中。当您使用它时,您可以通过添加int main 和必要的#includes 让每个人的生活更轻松。目标是在不进行任何修改的情况下复制“粘贴”您的代码到本地或在线编辑器,并使用实际的编译器对其进行测试。
  • Xcode 没有给我更复杂的错误,它在我尝试编译之前突出显示。

标签: c++ enums tuples c++14


【解决方案1】:

枚举类实际上并不是表面上的整数。就像只包含 int 的结构不是 int。

返回整数表示的 C++ 标准方法是这样的:

using UserUndT = std::underlying_type<User>::type;
std::cout << 
   std::get<static_cast<UserUndT>(User::FirstName)>(user) << std::endl;

另外,看看这个问题:Using enable_if and underlying_type in function signature in VS2012

一个值得考虑的替代方案:(C++14)

#include <iostream>
#include <tuple>

struct FirstName {
   std::string val;
};

struct LastName {
   std::string val;
};

using FullName = std::tuple<FirstName,LastName>;

int main() {
  auto user = FullName({"John"},{"Deer"});
  std::cout << std::get<FirstName>(user).val << std::endl;
  std::cout << std::get<LastName>(user).val << std::endl;
}

【讨论】:

  • 我本来想说“但是会员类型是”,然后突然想到不是这样的......
  • 您的 c++14 是否被认为是更好的设计模式?这似乎是一种有趣的方法,尽管随着字段数量的增加,它会导致创建更多的类。
  • 我使用了类似的东西,在可读性和类型安全方面取得了很好的效果(不是使用枚举或元组)。我想我是从 Scott Meyers 的 Effective C++,第 18 条使接口易于正确使用而难以错误使用中学到的,其中他有针对日、月、年的小类。他使用struct Day {explicit Day(int d):val(d){} int val;}; 使其更安全。另外:reddit.com/r/cpp/comments/3qbg70/…
  • 它实际上在那本书中(在关于作用域枚举的部分中)以我上面的方式使用枚举。编辑:抱歉,在另一本书中,“有效的现代 C++”
【解决方案2】:

为了得到你想要的,你可以做:

namespace User{enum User:size_t{FirstName,LastName};};

然后您将再次获得裸键入的枚举。

【讨论】:

    【解决方案3】:

    命名空间解决方案有效,但不适用于函数或类。一种替代方法如下:

    #include <iostream>
    #include <tuple>
    #include <vector>
    #include <string>
    using namespace std;
    
    int main()
    {
       struct Test{enum size_t{first, second, third};};
       vector<tuple<int, string, bool>> mt;
       mt.emplace_back(make_tuple(10, "hello", true));
       cout << get<Test::first>(mt[0]) << ' ' << get<Test::second>(mt[0]) << ' ' << get<Test::third>(mt[0]) << endl;
       return 0;
    }
    

    【讨论】:

    • 为什么是mt.emplace_back(make_tuple(10, "hello", true)); 而不是mt.emplace_back(10, "hello", true);
    猜你喜欢
    • 2019-09-13
    • 2014-11-22
    • 2022-06-22
    • 1970-01-01
    • 2016-09-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-29
    相关资源
    最近更新 更多