3

テンプレート引数リストをループする方法を見つけようとしていますが、成功しません

C++11 可変個引数テンプレート機能を使用できず、コンパイル時に行う必要があります

否定的な議論の後には肯定的な議論はないと想定できます

何か案が ?

template< int F1, int F2 ,int F3>
struct TemplatedClass
{
    TemplatedClass();
    update()
    {
        /* 
          for each positive template argument 
             call a method
        */
    }
};
4

5 に答える 5

5

一連のifステートメントを記述する代わりに、すべての引数を配列に入れて反復処理することもできます。この方法では、コンパイラはコードを最適化できません (これが必要かどうかは指定しませんでした) が、見た目はずっときれいになると思います。例えば

template<int F1, int F2 ,int F3>
struct TemplatedClass
{ 
    TemplatedClass(); 
    update() 
    {
        const int array[] = {F1, F2, F3};
        // replace this with std::for_each(...) with functors you need
        for (int i = 0; i < sizeof(array)/sizeof(array[0]); ++i)
        {
            myfunc(array[i]);
        }
    } 
} 
于 2012-07-19T13:59:00.303 に答える
3

テンプレート引数の数には限りがあるため、一連のifステートメントを使用できます。

template<int F1, int F2 ,int F3> 
struct TemplatedClass 
{ 
    TemplatedClass(); 
    update() 
    {
    if (F1 > 0) myfunc(); 
    if (F2 > 0) myfunc(); 
    if (F3 > 0) myfunc(); 
        // etc.*  
    } 
} 
于 2012-07-19T13:47:11.260 に答える
2

テンプレート引数の数を固定すると、次のような単純なコードで実行できます。

update()
{
    if (F1 > 0) callAMethod();
    if (F2 > 0) callAMethod();
    if (F3 > 0) callAMethod();
}

ステートメント内の式ifはコンパイル時の定数であるため、オプティマイザーは、メソッドを「保護されていない」(分岐なしで) 呼び出すか、メソッドをまったく呼び出さないのと同等のコードに最適化します。つまり、メソッドを呼び出すかどうかの決定は、実行時のコストなしでオプティマイザーによってコンパイル時に行われます。

于 2012-07-19T13:48:41.230 に答える
1

ifまたは、オプティマイザがsを取り除くかどうかわからない場合は、ヘルパー テンプレートを使用します。

void functionToCall(int number) { /* ... */ }

template<bool doCall>
struct FuncCaller {
    template<typename Callable>
    FuncCaller(Callable func, int number) { func(number); }
};

template<>
struct FuncCaller<false> {
    template<typename Callable>
    FuncCaller(Callable, int) {}
};

update()
{
    FuncCaller<(F1 > 0)>(functionToCall, F1);
    FuncCaller<(F2 > 0)>(functionToCall, F2);
    FuncCaller<(F3 > 0)>(functionToCall, F3);
}
于 2012-07-19T13:52:48.113 に答える
0

Boost Metaprogramming ライブラリを使用してそれを試すこともできますが、クラスのテンプレート定義を変更して Boost MPL パラメータ用のスペースを確保する必要があります。

Boost::MPL でやりたいことの例は次のようになります。

#include <boost/mpl/vector.hpp>
#include <boost/mpl/empty.hpp>
#include <boost/mpl/back.hpp>
#include <boost/mpl/pop_back.hpp>
#include <boost/mpl/if.hpp>
#include <iostream>

using namespace boost::mpl;
template<class T>
class Test {
public:
  void funcToCall() {
    std::cout << "I'm called\n";
  }
  void update();
};

template<class Y, class T>
struct Update {
  static void update(T* t) {
    typedef typename pop_back<Y>::type vec_less;
    if (back<Y>::type::value > 0)
      t->funcToCall();
    Update<typename if_<empty<vec_less>, void, vec_less >::type, T>::update(t);
  }
};
template<class T>
struct Update<void ,T> {
  static void update(T* t) {}
};

template<class T>
void Test<T>::update() {

Update<T, Test<T> >::update(this);

}


int main() {
  Test<vector<int_<0>,int_<4>, int_<9> > > t;
  t.update();
  return 0;
}

クラス「Test」は、元の「TemplatedClass」になります。int テンプレート パラメータのリストを取得する代わりに、boost::mpl::vector である 1 つのパラメータを取得するだけです。これには、渡したいすべての int が含まれており、int が 0 より大きい場合、構造体「Update」から更新メソッドを再帰的に呼び出す update 関数を呼び出します。この関数は、「funcToCall()」メソッドを呼び出す義務があります。

上に貼り付けたプログラムの出力は次のとおりです。

MacBook-Pro-di-Marcello:~ Kariddi$ ./test

私は呼ばれています

私は呼ばれています

もちろん、この例を機能させるには Boost ライブラリが必要です。

MPL に関する情報は、次の場所にあります。

http://www.boost.org/libs/mpl/doc/index.html

乾杯、マルチェロ

于 2012-07-19T16:53:21.360 に答える