2016-06-21 5 views
1

function_sigの関数ポインタ配列が与えられているので、テンプレートパラメータを介してインデックスとなるテンプレート関数ポインタのセットに初期化したいと思います。これは可能ですか?0..N-1からインデックス付けされた関数テンプレートへのN個の関数ポインタの配列を初期化する方法は?

など。

template<int I> 
void fn() { /* do something */ } 

typedef void(*function_sig)(); 

template<int ARRAY_SIZE> 
struct items 
{ 
    static function_sig array[ARRAY_SIZE]; 
}; 

template<int ARRAY_SIZE> 
function_sig items<ARRAY_SIZE>::array = { /* what do I put here? */ }; 

ので、items<ARRAY_SIZE>::array{ fn<0>, fn<1>, ..., fn<ARRAY_SIZE-1> }に初期化されるように、私は初期化子リストに入れることができる何かが、ありますか?

注:私はプリプロセッサの魔法でこれを行う方法を知っていますが、私はそれを試してみたいと思います。現在、配列を削除して配列のようなものに置き換える必要があると思っていますが、擬似配列のインデックスを作成するときにはO(N)の検索につながります。 dはしたくない。 C++ 14、int_seqstd::integer_sequenceらに有利に消えると

+0

になるこれらのQ&Aのヘルプあなたのいずれかを行います:[C++ 11 constexprの配列へのstd ::リスト配列をフラット化](http://stackoverflow.com/questions/25068481/ c11-constexpr-flat-list-of-stdarray-into-array)または[Implementation C++ 14 make_integer_sequence](http://stackoverflow.com/questions/17424477/implementation-c14-make-integer-sequence)? – MicroVirus

+0

@MicroVirus、これはおそらくC++ 11コンパイラ(VS2013)用です。私はまだそれらを読んで、私が何かを考え出すことができるかどうかを見ます。ありがとう。 – Adrian

答えて

0
#include <array> 

template<int... Is> 
struct int_seq { }; 

namespace detail { 

template<int I, int... Is> 
struct make_int_seq : make_int_seq<I - 1, I, Is...> { }; 

template<int... Is> 
struct make_int_seq<0, Is...> { 
    using type = int_seq<0, Is...>; 
}; 

} // namespace detail 

template<int SizeN> 
using make_int_seq = typename detail::make_int_seq<SizeN - 1>::type; 

template<int I> 
void fn() { /* do something */ } 

//typedef void(*function_sig)(); 
using function_sig = void(*)(); 

template<int ARRAY_SIZE> 
struct items { 
    static std::array<function_sig, ARRAY_SIZE> array; 
}; 

template<int... Is> 
std::array<function_sig, sizeof...(Is)> create_items_array(int_seq<Is...>) { 
    return {{ &fn<Is>... }}; 
} 

template<int ARRAY_SIZE> 
std::array<function_sig, ARRAY_SIZE> items<ARRAY_SIZE>::array 
    = create_items_array(make_int_seq<ARRAY_SIZE>{}); 

Online Demo

+0

これはc配列で動作しますか? – Adrian

+0

@Adrian:いいえ、C配列はコピーできないため、関数から返すことはできません。また、 'create_items_array'ファクトリ関数が必要です。 – ildjarn

+0

FYIでは、 'make_int_seq'が0..Nを生成するので、' std :: make_integer_sequence'が0..N-1を生成するので、C++ 14にアップグレードする際に若干の修正が必要です。 – Adrian

1

問題は0からARRAY_SIZE - 1までの可変範囲を取得することです。

Iは、基本クラスでitemsH

#include <iostream> 


template <std::size_t ...> 
struct range 
{ }; 

template <std::size_t N, std::size_t ... Next> 
struct rangeH 
{ using type = typename rangeH<N-1U, N-1U, Next ... >::type; }; 

template <std::size_t ... Next > 
struct rangeH<0U, Next ... > 
{ using type = range<Next ... >; }; 


template<int I> 
void fn() { std::cout << "[" << I << "]" << std::endl; } 

typedef void(*function_sig)(); 

template <typename T> 
struct itemsH; 

template <std::size_t ... RNG> 
struct itemsH<range<RNG...>> 
{ 
    static function_sig array[sizeof...(RNG)]; 
}; 

template<std::size_t ARRAY_SIZE> 
struct items : public itemsH<typename rangeH<ARRAY_SIZE>::type> 
{ }; 

template <std::size_t ... RNG> 
function_sig itemsH<range<RNG...>>::array[sizeof...(RNG)] = { fn<RNG>... }; 


int main() 
{ 
    items<10> i_10; 

    for (unsigned ui = 0U ; ui < 10 ; ++ui) 
     i_10.array[ui](); 

    return 0; 
} 

p.sをarrayを転送ソリューションを提案する:私はsize_tintARRAY_SIZEからの種類を変更しました。希望は問題ではない

p.s.2:私の悪い英語のために申し訳ありません。

---編集:追加C++ 14例---

(あなたがいる場合)C++ 14を使用することができますが、あなたは離れてrangerangeHを投げstd::index_sequencestd::make_index_sequenceを、使用することができた場合。

例は

#include <utility> 
#include <iostream> 


template<int I> 
void fn() { std::cout << "[" << I << "]" << std::endl; } 

typedef void(*function_sig)(); 

template <typename T> 
struct itemsH; 

template <std::size_t ... RNG> 
struct itemsH<std::index_sequence<RNG...>> 
{ static function_sig array[sizeof...(RNG)]; }; 

template<std::size_t ARRAY_SIZE> 
struct items : public itemsH<std::make_index_sequence<ARRAY_SIZE>> 
{ }; 

template <std::size_t ... RNG> 
function_sig itemsH<std::index_sequence<RNG...>>::array[sizeof...(RNG)] 
    = { fn<RNG>... }; 


int main() 
{ 
    items<10> i_10; 

    for (unsigned ui = 0U ; ui < 10 ; ++ui) 
     i_10.array[ui](); 

    return 0; 
} 
+0

あなたの英語は上質です。 'std :: size_t'への切り替えは問題ありません。私が怠け者だったので私は 'int'を使っただけです。 :D私は通常 'std :: size_t'を使います。 – Adrian

関連する問題