简体   繁体   English

使用可变参数模板和重载<<运算符编译错误

[英]Compile error with variadic templates and overloaded << operator

I'm trying to create a class that would store a tuple of vectors. 我正在尝试创建一个存储向量元组的类。 I have a strange compilation error whose origin I don't understand. 我有一个奇怪的编译错误,其起源我不明白。

The code: 编码:

#include <iostream>
#include <tuple>
#include <vector>

/// Suppose T is a pack of primitive types
/// VectorTuple defines a tuple of vectors of these types

template <typename... T>
struct VectorTuple;

template <typename T>
struct VectorTuple<T>
{
  using data_type = std::tuple<std::vector<T>>;
};

template <typename T1, typename T2>
struct VectorTuple<T1, T2>
{
  using data_type = std::tuple<std::vector<T1>, std::vector<T2>>;
};

template <typename T1, typename T2, typename T3>
struct VectorTuple<T1, T2, T3>
{
  using data_type = std::tuple<std::vector<T1>, std::vector<T2>, std::vector<T3>>;
};

// ----------------------------------------------------------------------------

template <size_t I, size_t N, typename... T>
struct DataAlgorithm
{
  static void resize(typename VectorTuple<T...>::data_type &data, const size_t size)
  {
    std::get<I>(data).resize(size);
    DataAlgorithm<I + 1, N, T...>::resize(data, size);
  }
};

// ----------------------------------------------------------------------------

template <size_t N, typename... T>
struct DataAlgorithm<N, N, T...>
{
  static void resize(typename VectorTuple<T...>::data_type &data, const size_t size)
  {
    std::get<N>(data).resize(size);
  }
};

// ----------------------------------------------------------------------------

template <typename... StoredTypes>
class MultiArray
{

public:
  enum
  {
    NFields = sizeof...(StoredTypes)
  };

  using value_types = std::tuple<StoredTypes...>;

  void resize(const size_t size)
  {
    DataAlgo<0, NFields - 1, StoredTypes...>::resize(m_values, size);
  }

private:
  template <size_t I, size_t N, typename... T>
  using DataAlgo = DataAlgorithm<I, N, T...>;

  using storage_type = typename VectorTuple<StoredTypes...>::data_type;

  /// The actual data stored
  storage_type m_values;
};


// This doesn't compile when array is const&, but works with non-const reference
template <typename... StoredTypes>
std::ostream &operator<<(std::ostream &os, const MultiArray<StoredTypes...> &array)
{
  os << std::endl; // This is line 86 in the compiler error message
  return os;
}

int main()
{
  MultiArray<double, int, float> array;

  return 0;
}

I'm not able to overload the "<<" operator with const MultiArray<...>& as parameter. 我无法使用const MultiArray<...>&作为参数重载“<<”运算符。 Clang 3.9.0 says: Clang 3.9.0说:

compile_error.cpp: In instantiation of ‘class MultiArray<>’:
compile_error.cpp:86:14:   required from here
compile_error.cpp:75:71: error: invalid use of incomplete type ‘struct VectorTuple<>’
   using storage_type = typename VectorTuple<StoredTypes...>::data_type;
                                                                       ^
compile_error.cpp:9:8: note: declaration of ‘struct VectorTuple<>’
 struct VectorTuple;

If I understand correctly, the compiler is not able to deduce the parameter types and tries to instantiate VectorTuple with no parameters whatsoever. 如果我理解正确,编译器无法推断出参数类型并尝试实例化VectorTuple带任何参数。 Could you please help me fix this? 你能帮帮我解决这个问题吗? Thank you. 谢谢。

This problem seems to be similar to the one described in this post . 这个问题似乎是类似于中描述的这个帖子

I also have a bonus question (but this should perhaps go to another post). 我也有一个奖金问题(但这可能应该转到另一个帖子)。 Is there a more generic way of transforming a parameter pack of primitive types to a tuple of vectors of these types? 是否有更通用的方法将基本类型的参数包转换为这些类型的向量元组? It would be nice to replace the explicit enumeration of different variants of VectorTuple based on increasing number of template parameters by something like this: VectorTuple根据增加的模板参数数量替换VectorTuple的不同变体的显式枚举,如下所示:

template<typename ... T> struct TransformToVectors { /* ?? implementation ?? */ };

such that 这样的

TransformToVectors<double, int, float>::type

would be an alias for 将是别名

std::tuple<std::vector<double>, std::vector<int>, std::vector<float>>

I tried to build the type recursively from instances with lower number of template parameters, but didn't get very far. 我试图从具有较少数量的模板参数的实例中递归地构建类型,但是没有达到很远。

For the bonus question 对于奖金问题

Is there a more generic way of transforming a parameter pack of primitive types to a tuple of vectors of these types? 是否有更通用的方法将基本类型的参数包转换为这些类型的向量元组? It would be nice to replace the explicit enumeration of different variants of VectorTuple based on increasing number of template parameters by something like this: 最好根据增加的模板参数数量替换VectorTuple的不同变体的显式枚举,如下所示:

 template<typename ... T> struct TransformToVectors { /* ? implementation ?? */ }; 

such that 这样的

 TransformToVectors<double, int, float>::type 

would be an alias for 将是别名

 std::tuple<std::vector<double>, std::vector<int>, std::vector<float>> 

What's wrong with 怎么了?

template<typename ... T>
struct TransformToVectors
 { using type = std::tuple<std::vector<T>...>; };

?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM