我想知道c++11/c++14是否支持类似vector<auto>
的东西?如果不支持,有什么原因吗?
这并不是直接支持的功能,也不清楚您想要做什么。
评论中已经提到了一些可能性(例如Boost的any
和variant
类)用于创建异构集合。希望这不是您想要的,因为异构集合与C++不太匹配,使用它们很丑陋和笨拙。我想在某些情况下/情况下,确实会是可用的最佳选择,但至少在我的经验中,这些情况相当罕见。
template <class T>
std::vector<T> make_vector(std::initializer_list<T> init) {
return std::vector<T>(init);
}
vector<T>
(其中T
是从初始化列表中数据类型推导出的),因此您可以执行以下操作:auto a = make_vector({ 1, 2, 3, 4 }); // a -> vector<int>
auto b = make_vector({ 1.0, 2.0, 3.0 }); // b -> vector<double>
auto c = make_vector({ "1"s, "2"s, "3"s }); // c -> vector<std::string>
make_vector
一样定义模板构造函数。这将允许您在构造函数上使用参数推断来推断整个类的模板参数,因此您可以执行类似以下内容的操作:X x(1); // deduces as X<int>
X x(2.0) // deduces as X<double>
注意:尽管已经有人提出了这个想法,但它并未被接受。它可能(很容易)永远不会被接受 - 即使被接受了,也可能在那之前发生重大变化。
不,C++11和C++14已经完成并发布了,没有这个功能。
但是,在Concepts工作的框架下,可能会出现vector<auto>
和类似的东西,比如tuple<auto...>
。
这很自然,因为std::vector<T>
可以在函数模板和部分特化的类模板中使用,其中T
是一个模板参数,而且多态lambda允许auto
作为函数参数类型(这是带有推断参数的函数模板的简写)。
概念技术规范允许像这样声明“泛型函数”:
auto func(auto arg);
由于您可以拥有这样的函数模板:
template<typename T>
auto func(std::vector<T> v);
将通用函数语法扩展以允许:
auto func(std::vector<auto> v);
一旦您在函数声明中允许这样做,那么也应该可以在变量声明中允许这样做:
std::vector<auto> v = function_returning_vector_of_something();
它没有出现在C++11中的原因是,auto
是新功能,尝试让它做太多事情会过于雄心勃勃。在C++14中,多态lambda表达式是新功能,再次扩展auto
的用途将是雄心勃勃的。
对于C++17,我们在实际代码中使用auto
的经验更丰富,编译器编写者熟悉实现它并知道不需要太多努力就可以做到什么。
std::vector<T>
зҡ„T
еҗ—пјҹзӣ®еүҚfunc({1, 2, 3, 4})
ж— жі•е·ҘдҪңгҖӮ - Jamboreeauto
,所以我已经改变了那个例子。 - Jonathan Wakelyboost::any
可以存储任何可复制的类型的实例,这是非常多的类型。
为了从你的 any
中获取数据,你必须知道你存储在其中的确切类型。
编写一个简单的 any
并不难:
#include <memory>
#include <utility>
struct any_internal {
virtual any_internal* clone() const = 0;
virtual ~any_internal() {};
};
template<class T>
struct any_details;
class any {
std::unique_ptr<any_internal> internal;
public:
any() = default;
any( any && ) = default;
any( any const&& o):any(o) {}
any( any & o ):any( const_cast<any const&>(o) ) {}
any& operator=( any && ) = default;
any& operator=( any const&& o ) { return this->operator=( o ); };
any& operator=( any & o ) { return this->operator=( const_cast<any const&>(o) ); };
any( any const& o ):internal( o.internal?o.internal->clone():nullptr ) {}
any& operator=( any const& o ) {
any tmp(o);
using std::swap;
swap( internal, tmp.internal );
return *this;
}
template<class U>
void reset( U&& o );
template<class U, class... Args>
void emplace( Args&&... args );
template<class U>
any( U&& o );
template<class U>
any& operator=(U&& o);
template<class T> T* get();
template<class T> T const* get() const;
template<class T> T* fast_get();
template<class T> T const* fast_get() const;
explicit operator bool() const { return internal!=nullptr; }
};
template<class T>
struct any_details : any_internal {
T t;
template<class...Args>
any_details( Args&&... args ):t(std::forward<Args>(args)...) {}
any_internal* clone() const override { return new any_details<T>{t}; }
};
template<class U, class... Args>
void any::emplace( Args&&... args ) {
internal.reset( new any_details<U>( std::forward<Args>(args)... ) );
}
template<class U>
void any::reset( U&& o ) {
emplace<typename std::decay<U>::type>( std::forward<U>(o) );
}
template<class U>
any::any( U&& o ) {
reset( std::forward<U>(o) );
}
template<class U>
any& any::operator=(U&& o) {
reset( std::forward<U>(o) );
return *this;
}
template<class T> T* any::get() {
auto* r = dynamic_cast< any_details<T>* >( internal.get() );
if (r) return &r->t;
return nullptr;
}
template<class T> T const* any::get() const {
auto* r = dynamic_cast< any_details<T>* >( internal.get() );
if (r) return &r->t;
return nullptr;
}
template<class T> T* any::fast_get() {
auto* r = static_cast< any_details<T>* >( internal.get() );
if (r) return &r->t;
return nullptr;
}
template<class T> T const* any::fast_get() const {
auto* r = static_cast< any_details<T>* >( internal.get() );
if (r) return &r->t;
return nullptr;
}
一个 std::vector<any>
的行为很像你希望 std::vector<auto>
做的。
通过小缓冲区优化(即,如果 t
很小,则在 any
中存储 T
,而不是使用堆),可以实现增加效率。
你可能还想将 get
与 fast_get
分开,其中 get
执行 dynamic_cast
,而 fast_get
执行 static_cast
,以提高效率。(当你确定时,可以使用 fast_get
)
基本上这是一个装饰过的 void*
。
any const&&
和 any&
的拷贝构造函数? - dypswap( internal, tmp.internal );
或者 internal = std::move(tmp.internal);
- dypmove
也可以工作:我正在做复制交换,然后懒得实现void swap(any&, any&)
,因为我注意到它只有两行长。感谢修复--这是即兴写的。 - Yakk - Adam NevraumontX& X::operator=(const X&)
的形式,否则,隐式声明的复制赋值运算符将采用X& X::operator=(X&)
的形式" -- 8.4.2/1 "显式默认的函数应该:...具有与隐式声明相同的声明函数类型(...)..." -- foo& operator(foo)
不是任何隐式声明特殊成员函数的声明函数类型,因此不能=default
。((...)
条款讨论了两个例外情况,但都不适用) - Yakk - Adam Nevraumont
std::vector< boost::any >
和std::vector< boost::variant<type0, type1, type2, type_and_so_on> >
。 - dyp