/ c ++ 11/14是否支持vector <auto> </auto>之类的东西

时间:2014-09-30 13:44:42

标签: c++11 c++14

我想知道c ++ 11 / c ++ 14是否/已经支持像vector<auto>这样的东西? 如果没有,有什么理由吗?

3 个答案:

答案 0 :(得分:8)

不直接支持,也不会立即明确您希望它做什么。

评论已经提到了一些用于创建异构集合的可能性(例如Boost anyvariant类)。我希望这不是你所追求的,因为异构集合与C ++的搭配很差,所以使用它们是丑陋而笨拙的。我认为有些情况/情况确实是最好的选择,但至少根据我的经验,这些情况相当罕见。

你可能想要的另一种可能的解释是一个向量(一般来说就像auto)只包含一个类型,但是这个类型是从初始化器中推导出来的,所以如果你从一些{{{ 1}} s,你得到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

最后一个需要用户定义的文字运算符,它是C ++ 14中的新功能(许多编译器还不支持)。其余的应该适用于C ++ 11。

N3602中也有一些讨论(以及{{3}}中的提议)添加一个功能(可能是C ++ 17),您可以在其中定义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

警告:这已被提议但未被接受。它可以(轻松地)永远被接受 - 即使它被接受,它也可能在发生之前被显着改变。

答案 1 :(得分:4)

不,不是在C ++ 11或C ++ 14中,已经完成并发布。

vector<auto>和类似tuple<auto...>之类的内容可能会在C ++ 17中作为Concepts工作的一部分。

很自然地,std::vector<T>可用于函数模板和类模板部分特化,T是模板参数,而且多态lambda允许{{1}作为函数参数类型(这是带有推导参数的函数模板的简写)。

概念TS允许将“通用函数”声明为:

auto

因为你可以有这样的功能模板:

auto func(auto arg);

将通用函数语法扩展为允许:

是有意义的
template<typename T>
  auto func(std::vector<T> v);

一旦你在函数声明中允许它,也应该可以在变量声明中允许它:

auto func(std::vector<auto> v);

它不在C ++ 11中的原因是std::vector<auto> v = function_returning_vector_of_something(); 是新的,并且过于雄心勃勃,试图让它做得太多。在C ++中,14多态lambdas是新的,再次,进一步扩展auto的使用将是雄心勃勃的。

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

答案 2 :(得分:1)

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_castfast_get执行static_cast,再次提高效率。 (如果您确切知道,可以fast_get

基本上这是一个谨慎的void*