我想知道c++11/c++14是否会/已经支持像vector<auto>这样的东西?若否,有何原因?
发布于 2014-09-30 23:12:05
它不是直接支持的,也不能立即明确你想要它做什么。
评论已经提到了创建异构集合的几种可能性(例如Boost any和variant类)。我希望这不是您想要的,因为异构集合不适合C++,所以使用它们是丑陋和笨拙的。我认为在某些情况下,这些确实是最好的选择,但至少在我的经验中,这些情况相当罕见。
您可能需要的另一种可能的解释是,向量(就像一般的auto一样)恰好包含一种类型,但该类型是从初始化器推导出来的,所以如果从一些int初始化向量,就会得到一个vector<int>,如果从一些字符串初始化,就会得到vector<string>,依此类推。尽管该语言不直接支持这一点,但至少在一定程度上可以很容易地模拟它。模板类不能/不能推导出模板参数,但模板函数可以/可以。因此,我们可以创建一个微型函数模板来获取一些初始化器,推导出它们的类型,并返回该类型的向量。例如:
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>最后一个需要一个用户定义的文字操作符,这在C++14中是新的(许多编译器还不支持)。剩下的用C++11就可以了。
还有一些讨论(以及N3602中的一项提议),即添加一个功能(可能是C++17),您可以在其中定义类似上面的make_vector的内容,但类似于类的模板构造函数。这将允许您在构造函数上使用实参推导来推导整个类的模板参数,因此您将能够执行以下操作:
X x(1); // deduces as X<int>
X x(2.0) // deduces as X<double>但是警告:这已经被提出,但没有被接受。它可能(很容易)永远不会被接受--即使它被接受了,在它发生之前,它也可能被显著地改变。
发布于 2014-10-01 00:45:36
不,不是C++11或C++14,它们已经完成并发布了。
但是,作为概念工作的一部分,vector<auto>和类似于tuple<auto...>的东西也有可能出现在C++17中。
这是很自然的,因为std::vector<T>可以用于函数模板和类模板部分专门化,其中T是一个模板参数,还因为多态lambdas允许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的经验,编译器编写人员也熟悉如何实现它,并且知道什么是不需要太多努力就能实现的。
发布于 2014-10-01 03:47:17
boost::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*。
https://stackoverflow.com/questions/26122450
复制相似问题