2009-08-15 47 views
6

は、私は与えられた型として扱う2つの入力に対する算術演算を実行するためのC++の関数をしたいと言う:テンプレート引数へのポインタを関数の引数として渡しますか?

擬似:OPに合わせ

function(var X,var Y,function OP) 
{ 
if(something) 
    return OP<int>(X,Y); 
else if(something else) 
    return OP<double>(X,Y); 
else 
    return OP<string>(X,Y); 
} 

の機能があるかもしれないように:

template <class T> add(var X,var Y) 
{ 
return (T)X + (T)Y; //X, Y are of a type with overloaded operators 
} 

ですから、関数のシグネチャはどのように見えますか?演算子関数がテンプレート化されていない場合、私はそれを行うことができますが、この余分な複雑さと混乱します。

+1

テンプレートテンプレートの引数を見てください。 (それはタイプミスではありません) – sbi

+0

+1、OPを渡す方法は基本的に正解です。 – MSalters

+0

これを回答として追加しました。私はそれに愚かな誤りを入れなかったことを願っています。 – sbi

答えて

4

これはお探しですか?

template<class T> T add(T X, T Y) 
{ 
    return X + Y; 
} 

または、addのようなものを探していますか?

int x = Apply(2, 4, add<int>); 
+0

私はテンプレート引数として* int *を指定せずに* add * **を渡したいと考えています。 – izogfif

5

私は少し混乱しています...あなたの擬似コードで、なぜ型分化:経由で呼び出され

template<class T, class F> 
T Apply(T x, T y, F f) 
{ 
    return f(x, y); 
} 

C++のテンプレートは、テンプレートの完全な型推論を許可:

ここ
template <typename T, typename F> 
T function(T x, T y, F op) { 
    return op(x, y); 
} 

F()関数呼び出し構文と呼ばれ、正確に2種類Tの引数(または暗黙的に受諾することができるもの(特に関数)をフィットそれに変換可能)。

+0

これは私が意味するものだと思う、テンプレート引数として関数を考えなかった。 –

+0

唯一の問題は、Fが未知のテンプレート引数を持つテンプレート関数であることができないこと、それがテンプレート以外の関数であること、またはすべてのテンプレートタイプが指定されたテンプレート関数でなければならないことです。 – izogfif

+0

@izogfifテンプレート引数を明示的に指定することもできます。それらを控除することは、テンプレートメタプログラミングを使用して行うことができます。しかし、とにかくこれはOPの質問に答えるように見え、それをさらに複雑にする必要はありません。 –

0

私はあなたの質問にこの意味varが何を意味するのか分かりません。確かに有効なC++キーワードではないので、boost:anyのようなタイプだと仮定します。また、関数に結果の型がありません。私は別のvarを追加しました。あなたの解は、次のようになります。

面白いテンプレート引数はテンプレートそのものであり、その名前は "テンプレートテンプレート引数"です。インスタンスではなく、テンプレートの名前を渡します。それはあなたがstd::plus、ないstd::plus<int>を渡し、次のとおりです。

return function(a, b, std::plus); 
+0

コンパイルエラーのため、Visual C++ 2008、Visual C++ 2010では動作しません。 – izogfif

+0

@izogfif:今すぐイメージングすると、正確なコンパイラエラーが発生しました。誰かが来て、それを見て、問題が何であるかを理解し、解決策を投稿したかもしれません。もちろん、私たちはこれを望んでいないので、あなたがそれを提供していないのは良いことです。 – sbi

+0

良い点。ここで私がコンパイルしようとしたコードとコンパイラ(コードの最後にある)によって生成されたエラーは:http://pastebin.com/YyhX9ruT – izogfif

5

テンプレート関数は、テンプレート引数として渡すことはできません。別のテンプレート関数に渡す前に、この関数のテンプレート引数を手動で推論する必要があります。

template<typename F, typename T> 
T callFunc(T a, T b, F f) 
{ 
    return f(a, b); 
} 

あなたは単にあなたが

int a = callFunc(1, 2, sum<int>); 
を記述する必要が

int a = callFunc(1, 2, sum); 

を書き込むことはできません:たとえば、あなたがcallFuncにそれを渡したい機能

T sum(T a, T b) 
{ 
    return a + b; 
} 

を持っています

渡すことができるようにするsumを書くことなく書かなければならないので、あなたのテンプレート関数を呼び出すfunctor-structまたはclassをoperator()で書く必要があります。次に、このファンクタをテンプレート引数として渡すことができます。ここに例があります。

template<class T> 
T sum(T a, T b) 
{ 
    return a + b; 
} 
template<class T> 
struct Summator 
{ 
    T operator()(T a, T b) 
    { 
     return sum<T>(a, b); 
    } 
}; 
template<template<typename> class TFunctor, class T> 
T doSomething(T a, T b) 
{ 
    return TFunctor<T>()(a, b); 
    //Equivalent to this: 
    //TFunctor<T> functor; 
    //return functor(a, b); 
} 


int main() 
{ 
    int n1 = 1; 
    int n2 = 2; 
    int n3 = doSomething<Summator>(n1, n2); //n3 == 3 
    return 0; 
} 
+0

人々は正しい用語を使用した場合、この混乱は最初に発生しません:テンプレート関数 "が存在しない場合、それらは"関数テンプレート "です。つまり、あなたの例 'callFunc(1、2、sum);では、関数を' callFunc'に渡すのではなく、*テンプレート*を渡しています。 *テンプレート引数としてテンプレートを渡しますが、* class *テンプレートのみを渡します。* function *テンプレートではありません。 –

+0

ええ、このように考えなかった。私は元の質問は、 "関数テンプレートを関数テンプレート引数として渡す方法"でなければならないと思います。 – izogfif

+0

sumがクラスの非静的メンバーである場合、このソリューションをどのように動作させるでしょうか? –

1

私はこれにラムダを使用します。

auto add = [](const auto& lhs, const auto& rhs) { 
    static_assert(std::is_arithmetic<typename std::decay<decltype(lhs)>::type>::value, 
      "Needs to be arithmetic."); 
    static_assert(std::is_arithmetic<typename std::decay<decltype(rhs)>::type>::value, 
      "Needs to be arithmetic."); 
    return lhs + rhs; 
}; 

template<typename LHS, typename RHS, typename FUNC 
    , typename OUT = typename std::result_of<FUNC(LHS, RHS)>::type> 
constexpr OUT do_arithmetic(LHS lhs, RHS rhs, FUNC func) { 
    return func(lhs, rhs); 
} 

constexpr auto t = do_arithmetic(40, 2, add); 
static_assert(t == 42, "Wrong answer!"); 
static_assert(std::is_same<std::decay<decltype(t)>::type, int>::value, 
     "Should be int."); 
関連する問題