如何获取向量中元素的类型?

时间:2014-01-28 07:54:25

标签: c++ c++11 vector stl

如果我有

,请考虑模板元编程技术
std::vector<int> v;
v.push_back(42.42f);

这是有效的,主要是因为使用它的构造函数没有标记为explicit,换句话说我的push_back它不是类型安全的。

现在我的情况是我甚至不知道如何声明容器v,在这种情况下它是int,但是我需要自动推断出类型std::vector<T>。我想要一个获得T的解决方案。

在C ++ 11中有类似remove_all_extents(有一个有用的成员type),但显然它只对旧数组有用,但它基本上是我想要实现的。

我想在push_back它不是类型安全的时候触发错误或者推断出类型,这样我就可以写一个断言或者自己实现一些东西。

我真的找不到一个有效的解决方案,它在理论上如此简单,但是一旦声明了一个向量,就没有关于元素所用类型的明确信息。

我还想避免明确的类型推断,比如从我理想的函数调用中翻译foo

foo( container, elements ... )

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

其中intcontainer元素的类型,在我看来这也不安全,它也更加冗长和容易出错。

那么如何在C ++ 11中检索容器元素的类型?

3 个答案:

答案 0 :(得分:9)

你可以得到这样的类型:

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

然后将static_assertstd::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

答案 1 :(得分:4)

如果您有C ++ 11功能,还可以使用decltype关键字来轻松访问value_type

decltype(TheContainer)::value_type nVarOfType;

TheContainer可能是任何类型的容器。例如map<int, string>deque<float>或任何其他STL容器,因为所有STL容器都具有value_type类型定义。 decltype将返回给定对象的类型。

答案 2 :(得分:2)

如果我理解正确的评论,您也可以尝试:

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

同样,你可以&#34;启用&#34;只有满足您对值类型的要求的模板:

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
}

编辑:

使用更多&#34;模板技巧&#34;,您可以确保所有类型的可变参数模板包都相等并且等于容器的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`

虽然语法可能看起来很奇怪,但如果参数包true中的所有类型都具有其拷贝构造函数不会抛出的属性,则上面的const表达式求值为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
}