2013-08-01 20 views
7

、私は難解なテンプレートの魔法のこのシンプルな作品を動作させることはできません。テンプレートテンプレート関数のパラメータ

template<typename T, int a, int b> 
int f(T v){ 
    return v*a-b; // just do something for example 
} 

template<typename T, int a, int b, template<typename,int,int> class func> 
class C{ 
    int f(){ 
    return func<T,a,b>(3); 
    } 
}; 

int main(){ 
    C<float,3,2, f> c; 
} 

はファンクタを介さずに行うことは可能、このですか?

+0

達成しようとしているのは正確ですか? – nijansen

+0

このコードの実行中にコンパイラがクラッシュしました。 – Saksham

+0

@nijansenはMSVS2010が安定していませんか? – Saksham

答えて

7

fはクラスとみなされています - あなたは関数を持っています。

以下を参照してください。

#include <iostream> 


template<typename T, int a, int b> 
int f(T v) 
{ 
    std::cout << "Called" << std::endl; 
    return v*a-b; // just do something for example 
} 

template<typename T, int a, int b, template<typename,int,int> class func> 
struct C 
{ 
    int f() 
    { 
    return func<T,a,b>(3); 
    } 
}; 

template <class T, int a, int b> 
struct FuncAdapt 
{ 
    T x_; 
    template <class U> 
    FuncAdapt(U x) 
    : x_(x) 
    {} 
    operator int() const 
    { 
    return f<T,a,b>(x_); 
    } 
}; 

int main() 
{ 
    C<float,3,2, FuncAdapt > c; 
    c.f(); 
} 
+0

あなたの最初のポイントをおめでとうございます – Saksham

+0

ありがとうございます。私は誰かをアップアップするための評判が必要だと思うので...私は質問に答えました。 –

+0

OPはファンクタを使わずにOPを望んでいませんでしたか? (引用:「これはファンクタを関与させることなく可能ですか?」) –

-1

いいえ、そうではありません。構文も:

template <typename T, int a, int b, template <typename, int, int> class func> 
                    ^^^^^ 

は、テンプレートテンプレートパラメータの引数がクラステンプレートでなければならないことを示しています。

+0

はい、私は単体テストコードをもっときちんとしたものにするために、生産コードを変更しないようにちょっとしたトリッキーを探していました。 –

0

あなたのコンパイラがある理由:あなたはポートレガシーコード(クラステンプレートに機能を適応させる)する必要がある場合

// Class acts like a function - also known as functor. 
template<typename T, int a, int b> 
class f 
{ 
    int operator()(T v) 
    { 
    return v*a-b; // just do something for example 
    } 
}; 

template<typename T, int a, int b, template<typename,int,int> class func> 
class C 
{ 
    int f() 
    { 
    return func<T,a,b>(3); 
    } 
}; 

int main() 
{ 
    C<float,3,2, f> c; 
} 

を...そして適応バージョンクラスとしてCの最後のテンプレートパラメータに関数(f)を渡しているという不満があります。

関数をテンプレートパラメータとして渡すことはできないため、関数ポインタまたは関数ファンクタを使用する必要があります。そして、ファンクターは間違いなくこれを行うためのよりクリーンな方法です。

したがって、ファンクターを使用せずに、あなたが望むものを達成することは可能ですが、実際には試してはいけません。

あなたはこのような何かを見ていることになる関数ポインタを使用したい場合:私はあなたがcの宣言でコードの重複を排除することができるだろうとは思わないような場合には

template<typename T, int a, int b, int (*func)(T)> 
class C{ 
    int f(){ 
     return (*func)(3); 
    } 
}; 

int main(){ 
    C< float,3,2,&f<float,3,2> > c; 
} 

、しかし私は間違っているかもしれません。あなたは少し策略を通してそれを解決することができ

6

template<typename T, int a, int b> 
int f(T v){ 
    return v*a-b; // just do something for example 
} 

template<typename T, int, int> 
using func_t = int (*)(T); 

template<typename T, int a, int b, func_t<T, a, b> func> 
class C{ 
    int f(){ 
    return func(3); 
    } 
}; 

C<float,3,2, f<float, 3, 2>> c; 

まず、機能(上記func_t)のための型の別名を必要とする、とあなたは、残念ながらcの宣言にテンプレート引数を複製する必要があります。

+1

...あなたのコンパイラがテンプレートエイリアスをサポートしている場合、C++ 11で。 MSVC 2013 * still * does not – SteveLove

+0

テンプレート引数の重複を避けたいと思っています。これは私の単体テストに多量の入力/コピーを保存しないようになっています。それからAppart、これはこれまでのところ最高の答えです。 –

関連する問題