通过作用域和类型枚举访问tuple值失败

时间:2021-07-08 16:38:55

When attempting to access a tuple's value via a scoped and typed enum, I get an error saying there is no matching type for std::get.

当试图通过作用域和类型化的枚举访问元组的值时,我得到一个错误,说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;

Given that std::get expects type std::size_t and the underlying type of the enum is also std::size_t, why does this fail?

给定std:::get预期类型std: size_t,枚举的底层类型也是std::size_t,为什么会失败?

I'm aware that I can cast the value of the enum, but I'm not sure why that would be necessary given that both underlying types are the same. With an unscoped enum, this works just fine.

我知道我可以设置enum的值,但是我不确定为什么需要这样做,因为这两个底层类型是相同的。在一个无作用域的enum中,这可以很好地工作。

3 个解决方案

#1


5  

Enum classes really aren't integers on the surface. Just like a struct containing just an int is not an int.

Enum类在表面上实际上不是整数。就像一个只包含int的结构体不是int。

The C++ standard way back to the integer representation is this:

回到整数表示的c++标准方法是:

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

Also, check out this question: Using enable_if and underlying_type in function signature in VS2012

另外,请查看这个问题:在VS2012中使用enable_if和underlying_type函数签名。

An alternative worth considering: (C++14)

一个值得考虑的替代方案:(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;
}

#2


0  

to get what you want you can do:

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

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

then you will have the bare typed enum again.

然后您将再次得到空类型的enum。

#3


0  

The namespace solution works but not inside a function or class. An alternative is as follows:

命名空间解决方案可以工作,但不能在函数或类中工作。另一种选择如下:

#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;
}

#1


5  

Enum classes really aren't integers on the surface. Just like a struct containing just an int is not an int.

Enum类在表面上实际上不是整数。就像一个只包含int的结构体不是int。

The C++ standard way back to the integer representation is this:

回到整数表示的c++标准方法是:

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

Also, check out this question: Using enable_if and underlying_type in function signature in VS2012

另外,请查看这个问题:在VS2012中使用enable_if和underlying_type函数签名。

An alternative worth considering: (C++14)

一个值得考虑的替代方案:(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;
}

#2


0  

to get what you want you can do:

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

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

then you will have the bare typed enum again.

然后您将再次得到空类型的enum。

#3


0  

The namespace solution works but not inside a function or class. An alternative is as follows:

命名空间解决方案可以工作,但不能在函数或类中工作。另一种选择如下:

#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;
}