首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >c++11/14是否支持像vector<auto>这样的东西

c++11/14是否支持像vector<auto>这样的东西
EN

Stack Overflow用户
提问于 2014-09-30 21:44:42
回答 3查看 254关注 0票数 5

我想知道c++11/c++14是否会/已经支持像vector<auto>这样的东西?若否,有何原因?

EN

回答 3

Stack Overflow用户

发布于 2014-09-30 23:12:05

它不是直接支持的,也不能立即明确你想要它做什么。

评论已经提到了创建异构集合的几种可能性(例如Boost anyvariant类)。我希望这不是您想要的,因为异构集合不适合C++,所以使用它们是丑陋和笨拙的。我认为在某些情况下,这些确实是最好的选择,但至少在我的经验中,这些情况相当罕见。

您可能需要的另一种可能的解释是,向量(就像一般的auto一样)恰好包含一种类型,但该类型是从初始化器推导出来的,所以如果从一些int初始化向量,就会得到一个vector<int>,如果从一些字符串初始化,就会得到vector<string>,依此类推。尽管该语言不直接支持这一点,但至少在一定程度上可以很容易地模拟它。模板类不能/不能推导出模板参数,但模板函数可以/可以。因此,我们可以创建一个微型函数模板来获取一些初始化器,推导出它们的类型,并返回该类型的向量。例如:

代码语言:javascript
复制
template <class T>
std::vector<T> make_vector(std::initializer_list<T> init) {
    return std::vector<T>(init);
}

这将返回一个vector<T> (带有从初始化器列表中的数据类型推导出的T ),因此您可以执行以下操作:

代码语言:javascript
复制
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的内容,但类似于类的模板构造函数。这将允许您在构造函数上使用实参推导来推导整个类的模板参数,因此您将能够执行以下操作:

代码语言:javascript
复制
X x(1);     // deduces as X<int>
X x(2.0)    // deduces as X<double>

但是警告:这已经被提出,但没有被接受。它可能(很容易)永远不会被接受--即使它被接受了,在它发生之前,它也可能被显著地改变。

票数 8
EN

Stack Overflow用户

发布于 2014-10-01 00:45:36

不,不是C++11或C++14,它们已经完成并发布了。

但是,作为概念工作的一部分,vector<auto>和类似于tuple<auto...>的东西也有可能出现在C++17中。

这是很自然的,因为std::vector<T>可以用于函数模板和类模板部分专门化,其中T是一个模板参数,还因为多态lambdas允许auto作为函数参数类型(这是带有推导参数的函数模板的简写)。

代码语言:javascript
复制
auto func(auto arg);

因为您可以拥有如下所示的函数模板:

代码语言:javascript
复制
template<typename T>
  auto func(std::vector<T> v);

代码语言:javascript
复制
auto func(std::vector<auto> v);

一旦您在函数声明中允许这样做,那么在变量声明中也应该可以这样做:

代码语言:javascript
复制
std::vector<auto> v = function_returning_vector_of_something();

它不在C++11中的原因是auto是新的,如果试图让它做太多事情,那就太雄心勃勃了。在C++14中,多态的lambda是新的,再一次,进一步扩展auto的用途是雄心勃勃的。

对于C++17,我们有更多在实际代码中使用auto的经验,编译器编写人员也熟悉如何实现它,并且知道什么是不需要太多努力就能实现的。

票数 4
EN

Stack Overflow用户

发布于 2014-10-01 03:47:17

boost::any可以存储可复制的任何类型的实例,这是许多类型。

为了从any中获取数据,您必须知道存储在其中的确切类型。

编写一个简单的any并不难:

代码语言:javascript
复制
#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中,而不是使用堆)。

为了提高效率,您可能还想将getfast_get中分离出来,get执行dynamic_castfast_get执行static_cast。(当你确定的时候,你可以fast_get)

基本上,这是一个美化的void*

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26122450

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档