使用可变参数模板编译错误并重载<<操作者

时间:2016-11-21 22:29:06

标签: c++ c++11 templates template-meta-programming

我正在尝试创建一个存储向量元组的类。我有一个奇怪的编译错误,其起源我不明白。

代码:

#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;
}

我无法重载“&lt;&lt;”以const MultiArray<...>&为参数的运算符。 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;

如果我理解正确,编译器无法推断出参数类型,并尝试在没有任何参数的情况下实例化VectorTuple。你能帮帮我解决这个问题吗?谢谢。

此问题似乎与this post中描述的问题类似。

我也有一个红利问题(但这可能应该转到另一个帖子)。是否有更通用的方法将基本类型的参数包转换为这些类型的向量元组?最好根据模板参数的增加来替换VectorTuple的不同变体的显式枚举,如下所示:

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

这样

TransformToVectors<double, int, float>::type

将是

的别名
std::tuple<std::vector<double>, std::vector<int>, std::vector<float>>

我尝试从模板参数较少的实例中递归构建类型,但是没有走得太远。

1 个答案:

答案 0 :(得分:0)

奖金问题

  

是否有更通用的方法来转换参数包   原始类型到这些类型的向量元组?这会很好   替换不同变体的显式枚举   VectorTuple基于增加的模板参数数量   像这样的东西:

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

这样

TransformToVectors<double, int, float>::type
     

将是

的别名
std::tuple<std::vector<double>, std::vector<int>, std::vector<float>>

有什么问题
template<typename ... T>
struct TransformToVectors
 { using type = std::tuple<std::vector<T>...>; };