How to get the type of elements in a vector?

Consider methods for metaprogramming patterns, if I have

std::vector<int> v;
v.push_back(42.42f);

this works mainly because the constructor used is not flagged explicit, in other words, my push_backtype is not safe.

Now I’m in a situation where I don’t even know how the container is declared v, in this case it is int, but I need to automatically output this type, having a common one std::vector<T>. I would like a solution T.

in C ++ 11 there is something like remove_all_extents(with a useful member type), but apparently this is only useful for old arrays, but this is basically what I would like to achieve.

I would like to raise an error when push_backit is not safe or type deduces, so that I can write a statement or implement something myself.

I really cannot find a working solution for this, it is so simple in theory, but as soon as the vector is declared, there is no explicit information about the type used for the elements.

I would also like to avoid explicit type inference, for example, translating foofrom my call to an ideal function

foo( container, elements ... )

to

foo<int>(container, elements ...)

where intis the type of elements container, it is also unsafe, it is also more detailed and error prone.

So, how do I get the type for container elements in C ++ 11?

+4
source share
3 answers

You can get this type:

typename std::vector<T>::value_type;

static_assert std::is_same.

template <typename T1, typename T2>
void special_push_back(std::vector<T1>& v, T2 elem)
{
  // check that T1 and T2 are the same before pushing elem into v
}

std::vector<int> v;
special_push_back(v, 3.14); // Compile time error: double is not int
+8

, :

template <class Container, class... Args>
void foo(Container&& c, Args&&... args) {
    typedef typename Container::value_type value_type;

    // use type_traits to check value_type
    ...
}

, , Container value_type:

template <class T>
struct has_value_type
{
private:
    template <class U> static std::false_type test(...);
    template <class U> static std::true_type test(typename U::value_type*);
public:
    enum { value = decltype(test<T>(0))::value };
};

std::enable_if:

template <class Container, class... Args>
typename std::enable_if<has_value_type<Container>::value, return_type>::type 
foo(Container&& c, Args&&... args) {
    typedef typename Container::value_type value_type;
    ...
}

"" , :

template <class Container, class... Args>
typename std::enable_if<
    has_value_type<Container>::value
    and std::is_same<int, typename Container::value_type>::value
>::type
foo2(Container&& c, Args&&... args) {
    typedef typename Container::value_type value_type;

    // here value_type equals int
}

Edit:

" " , , , value_type :

, :

template <typename...>
struct all_of;

template <typename T>
struct all_of<T> : std::conditional<T::value == true,
    std::true_type, std::false_type>::type
{};

template <typename Head, typename... Tail>
struct all_of<Head, Tail...> : std::conditional<
    Head::value == true and all_of<Tail...>::value,
    std::true_type,
    std::false_type>::type
{};

- , , :

`all_of<std::is_nothrow_copy_constructible<Args>...>::value`

, const true, Args , - .

- all_of, foo, value_type :

template <class Container, class... Args>
typename std::enable_if<
    has_value_type<Container>::value
    and all_of<std::is_same<typename Container::value_type, Args>...>::value
>::type
foo2(Container&& c, Args&&... args) {
    typedef typename Container::value_type value_type;

    // here *all* types in Args are equal value_type
}
+2

++ 11, decltype, value_type:

decltype(TheContainer)::value_type nVarOfType;

TheContainer . , map<int, string>, deque<float> STL, STL value_type. decltype .

: V++, . SO

+1

Source: https://habr.com/ru/post/1524013/


All Articles