1

配列の長さを後で constexpr で使用できる、任意の (ただし一定の) 長さの std::arrays のセットを格納する方法はありますか?

標準コンテナは論外だと思いますが、何らかのテンプレート ソリューションがあるかもしれません。すべての情報はコンパイル時に利用可能ですよね?

コード例:

#include <iostream>
#include <string>
#include <vector>
#include <array>
#include <algorithm>

// Class storing an array of any (but constant) size
struct A {
    const std::vector<std::string> container; 
    const int container_size;
    A(const std::vector<std::string>& v, int size) : container(v), container_size(size) { }
};

int main() {
    // List of variable length const arrays and their sizes
    std::vector<A> myAList {
        A({ std::string("String1"), std::string("String2") }, 2),
        A({ std::string("String1") }, 1)
    };

    // How would I go about using the size of each array in a constexpr?
    for (auto const& a : myAList) {
    // Example constexpr:
    //  somefunc(std::make_index_sequence<a.container_size>{});

    // 2nd example converting to actual std::array
    //  std::array<std::string, a.container_size> arr;
    //  std::copy_n(std::make_move_iterator(a.begin()), a.container_size, arr.begin());
    }

    return 0;
}

アップデート:

詳細が求められたので、ここに行きます。配列がどのように定義されているか、機能するものは何でも気にしません...使用される正確な constexpr は、サンプルコードのものですstd::make_index_sequence<CONSTEXPR>{}コンパイル時に定義された一連の定数配列があることを知っているだけで、 constexpr の他の場所でそれらの長さを参照できるはずです。

一体、私は実際には長さを保存するだけで問題ありません:

// Class storing an array size
struct A {
    A(int size) : container_size(size) { }
    const int container_size;
};

int main() {
    // List of lengths
    std::vector<A> mySizeList { 2, 1 };

    for (auto const& a : mySizeList) {
    //  somefunc(std::make_index_sequence<a.container_size>{});
    }
    return 0;
}
4

2 に答える 2

3

これは、と のsomefunc両方でを呼び出す必要があり、 のみを呼び出すことを前提としています。また、拡張シグネチャを使用した のサポートも提供します(単純に、戻り値および/または の後に渡される追加の引数を含む 3 番目の引数を渡します)。const&std::vectorindex_sequencesomefuncsomefuncstd::vector<T> const&

ベクトルのサイズを渡されたサイズに揃えないと、渡されたサイズがベクトルよりも長い場合に問題が発生します。

また、構築の時点で呼び出している関数を知っていることも前提としています。これは、当然のことながら、構築の時点で呼び出したい関数の任意の有限セットに一般化できます。

使用される手法は、「型消去」または「実行時の概念」と呼ばれます。構築中に問題のインデックス シーケンスであなたを呼び出すという概念まで消去し、some_func消去した操作を に保存しfます。

template<size_t N>
using size=std::integral_constant<size_t, N>;

template<
  class T, template<class...>class Operation,
  class Sig=std::result_of_t<Operation<size<0>>(std::vector<T> const&)>()
>
struct eraser;

template<class T, template<class...>class Operation, class R, class...Args>
struct eraser<T,Operation, R(Args...)> {
  std::vector<T> data;
  R(*f)(eraser const*, Args&&...);
  R operator()(Args...args)const{
    return f(this, std::forward<Args>(args)...);
  }
  template<size_t N>
  eraser( std::initializer_list<T> il, size<N> ):
    eraser( il.begin(), size<N>{} )
  {}
  template<class...Ts>
  eraser( T t0, Ts... ts ):
    eraser(
      {std::forward<T>(t0), std::forward<Ts>(ts)...},
      size<sizeof...(ts)+1>{}
    )
  {}
  template<size_t N>
  eraser( T const* ptr, size<N> ):
    data(ptr, ptr+N),
    f([](eraser const*self, Args&&...args)->R{
      return Operation<size<N>>{}(self->data, std::forward<Args>(args)...);
    })
  {}
};
template<class T, size_t ... Is>
void some_func( std::vector<T> const&, std::index_sequence<Is...>) {
  std::cout << "called! [#" << sizeof...(Is) << "]\n";
}
template<class N>
struct call_some_func {
  template<class T>
  void operator()(std::vector<T> const& v) const {
    some_func( v, std::make_index_sequence<N{}>{} );
  }
};


int main() {
  using A = eraser<std::string, call_some_func>;
  // List of variable length const arrays and their sizes
  std::vector<A> myAList {
    A({ std::string("String1"), std::string("String2") }, size<2>{}),
    A({ std::string("String1") }, size<1>{})
  };

  std::cout << "Objects constructed.  Loop about to start:\n";

  // How would I go about using the size of each array in a constexpr?
  for (auto const& a : myAList) {
    a();
  }
}

実際の例

于 2015-07-10T17:45:09.237 に答える
0

dynarrayあなたが望むのは、瀕死のようなものだと思います。

ただし、そのサイズを定数式で使用することはできません。これは、コンパイル時の定数ではないためです (名前の「dyn」が指すものです)。

container_size定数式でを使用するには、型Aはリテラル型でなければならないため、constexprコンストラクターが必要ですvector

あなたはこのようなことをすることができますが、それはかなり嫌です:

#include <array>

struct A
{
    void* ap;
    std::size_t n;
    template<std::size_t N>
      constexpr A(std::array<int, N>& a) : ap(&a), n(N) { }
    template<std::size_t N>
        std::array<int, N>& get() const { return *static_cast<std::array<int, N>*>(ap); }
    constexpr std::size_t size() const { return n; }
};

int main()
{
    static std::array<int, 3> a{ 1, 2, 3 };
    constexpr A aa(a);
    constexpr int len = aa.size(); // OK, this is a constant expression
    std::array<int, aa.size()>& r = aa.get<aa.size()>();        
}
于 2015-07-10T17:07:06.353 に答える