Ian Ian - 18 days ago 6
C++ Question

Accessing tuple value via scoped and typed enum fails

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
.

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?

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.

Answer

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

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

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

An alternative worth considering: (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;
}