How to get element from std::tuple by type

后端 未结 3 400
别跟我提以往
别跟我提以往 2020-12-19 11:54

I have a set of classes A, B, C and I want to have access instances of them from generic code by type, f.e

template
newObject()
{
    retur         


        
相关标签:
3条回答
  • 2020-12-19 12:02

    A simple variadic mixin container does the trick:

    template < typename T > struct type_tuple_value 
    { 
        T value; 
        type_tuple_value ( T&& arg ) : value(std::forward<T>(arg)) {}
    };
    
    template < typename ...T > struct type_tuple : type_tuple_value<T>...
    {
        template < typename ...Args > type_tuple ( Args&&... args ) :
        type_tuple_value<T>(std::forward<T>(args))... {}
        template < typename U > U& get() { return type_tuple_value<U>::value; }
        template < typename U > const U& get() const { return type_tuple_value<U>::value; }
    };
    

    Example

    0 讨论(0)
  • 2020-12-19 12:18

    This is a draft from C++14 about getting value from tuple by type.

    But before C++14 will come, you could write something like below:

    namespace detail
    {
    
    template <class T, std::size_t N, class... Args>
    struct get_number_of_element_from_tuple_by_type_impl
    {
        static constexpr auto value = N;
    };
    
    template <class T, std::size_t N, class... Args>
    struct get_number_of_element_from_tuple_by_type_impl<T, N, T, Args...>
    {
        static constexpr auto value = N;
    };
    
    template <class T, std::size_t N, class U, class... Args>
    struct get_number_of_element_from_tuple_by_type_impl<T, N, U, Args...>
    {
        static constexpr auto value = get_number_of_element_from_tuple_by_type_impl<T, N + 1, Args...>::value;
    };
    
    } // namespace detail
    
    template <class T, class... Args>
    T get_element_by_type(const std::tuple<Args...>& t)
    {
        return std::get<detail::get_number_of_element_from_tuple_by_type_impl<T, 0, Args...>::value>(t);
    }
    
    int main()
    {
        int a = 42;
    
        auto t = std::make_tuple(3.14, "Hey!", std::ref(a));
    
        get_element_by_type<int&>(t) = 43;
    
        std::cout << a << std::endl;
    
        // get_element_by_type<char>(t); // tuple_element index out of range
    
        return 0;
    }
    
    0 讨论(0)
  • 2020-12-19 12:26

    You can also compute the position of the type with a constexpr function if you don't like template.

      constexpr int count_first_falses() { return 0; }
    
      template <typename... B>
      constexpr int count_first_falses(bool b1, B... b)
      {
        if (b1) return 0;
        else return 1 + count_first_falses(b...);
      }
    
      template <typename E, typename... T>
      decltype(auto) tuple_get_by_type(const std::tuple<T...>& tuple)    
      {
        return std::get<count_first_falses((std::is_same<T, E>::value)...)>(tuple);
      }
    
    0 讨论(0)
提交回复
热议问题