std::get using enum class as template argument

后端 未结 6 1606
孤街浪徒
孤街浪徒 2021-01-04 07:40

I\'m using a std::tuple and defined a class enum to somehow \"naming\" each of the tuple\'s fields, forgetting about their actual indexes.

So instead o

相关标签:
6条回答
  • 2021-01-04 07:53

    A completely different solution would be:

    A& my_field(std::tuple<A,B>& t) { return std::get<0>(t); }
    A const& my_field(std::tuple<A,B> const& t) { return std::get<0>(t); }
    
    B& my_other_field(std::tuple<A,B>& t) { return std::get<1>(t); }
    B const& my_other_field(std::tuple<A,B> const& t) { return std::get<1>(t); }
    
    my_field(t) = blah;
    my_other_field(t) = frob;
    
    0 讨论(0)
  • 2021-01-04 07:57

    2018 update:

    It's not a problem anymore. I did have a problem when I tried variations of "enum class int", but this now works fine with VS 2017 15.7.2

    enum 
    {
      WIDTH,
      HEIGHT
    };
    std::get<HEIGHT>( Remaining ) = std::get<HEIGHT>( Remaining ) - MinHeight;
    
    0 讨论(0)
  • 2021-01-04 08:03

    My solution is to use:

    namespace Something{enum class Something {MY_INDEX_NAME = 0,OTHER_INDEX_NAME};};
    
    0 讨论(0)
  • 2021-01-04 08:07

    Yes, this was a bug in GCC 4.5. Scoped enums don't have implicit conversions to integral types.

    0 讨论(0)
  • 2021-01-04 08:13

    The strongly-typed enums introduced by C++11 cannot be implicitly converted into integral values of type say int, while std::get expects the template argument to be integral type.

    You've to use static_cast to convert the enum values:

    std::cout <<std::get<static_cast<int>(Bad::BAD)>(tup)<< std::endl; //Ok now!
    

    Or you can choose to convert into underlying integral type as:

    //note that it is constexpr function
    template <typename T>
    constexpr typename std::underlying_type<T>::type integral(T value) 
    {
        return static_cast<typename std::underlying_type<T>::type>(value);
    }
    

    then use it as:

    std::cout <<std::get<integral(Bad::BAD)>(tup)<< std::endl; //Ok now!
    
    0 讨论(0)
  • 2021-01-04 08:13

    I'd like to add another answer because the original poster asked for a way to have a named access to elements of std::tuple through a class enum.

    It is possible to have a template argument of the type of a class enum (at least in GCC). This makes it possible to define your own get retrieving the element of a tuple given a class enum value. Below is an implementation casting this value to int, but you could also do something more fancy:

    #include <tuple>
    
    enum class names { A = 0, B, C };
    
    template< names n, class... Types >
    typename std::tuple_element<static_cast< std::size_t >( n ), std::tuple<Types...> >::type&
        get( std::tuple<Types...>& t )
    {
        return std::get< static_cast< std::size_t >( n ), Types... >( t );
    }
    
    int main( int, char** )
    {
        std::tuple< char, char, char > t( 'a', 'b', 'c' );
        char c = get<names::A>( t );
    }
    

    Note that std::get has two more variants (one for const tuple&, one for tuple&&), which can be implemented exactly the same way.

    0 讨论(0)
提交回复
热议问题