如果我有
,请考虑模板元编程技术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 ...)
其中int
是container
元素的类型,在我看来这也不安全,它也更加冗长和容易出错。
那么如何在C ++ 11中检索容器元素的类型?
答案 0 :(得分:9)
你可以得到这样的类型:
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
答案 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
}