2017-03-17 2 views

答えて

1

これをC++ 17またはC++ 14で実装する方がはるかに簡単ですっきりしていますが、というタグが付いているので、ここには準拠した実装があります。ここでは、同じ引数を持つ関数オブジェクトfを呼び出す一般的な方法をN回繰り返します。

まず、我々は、一般的な関数オブジェクトfの最初の引数を結合する方法を必要として、任意の数の引数受諾:次に

template <typename TF, typename T> 
struct bound 
{ 
    TF _f; 
    T _x; 

    template <typename TFFwd, typename TFwd> 
    bound(TFFwd&& f, TFwd&& x) 
     : _f{std::forward<TFFwd>(f)}, _x{std::forward<TFwd>(x)} 
    { 
    } 

    template <typename... Ts> 
    auto operator()(Ts&&... xs) 
     -> decltype(_f(_x, std::forward<Ts>(xs)...)) 
    { 
     return _f(_x, std::forward<Ts>(xs)...); 
    } 
}; 

template <typename TF, typename T> 
auto bind_first(TF&& f, T&& x) 
    -> decltype(bound<TF&&, T&&>(std::forward<TF>(f), std::forward<T>(x))) 
{ 
    return bound<TF&&, T&&>(std::forward<TF>(f), std::forward<T>(x)); 
} 

を、私たちは、引数を結合する再帰helperが必要x複数TN回:

template <std::size_t TN> 
struct helper 
{ 
    template <typename TF, typename T> 
    auto operator()(TF&& f, T&& x) 
     -> decltype(helper<TN - 1>{}(bind_first(std::forward<TF>(f), x), x)) 
    { 
     return helper<TN - 1>{}(bind_first(std::forward<TF>(f), x), x); 
    } 
}; 

template <> 
struct helper<0> 
{ 
    template <typename TF, typename T> 
    auto operator()(TF&& f, T&& x) 
     -> decltype(f(x)) 
    { 
     return f(x); 
    } 
}; 

最後に、私たちは素敵なインターフェースを提供することができます

template <std::size_t TN, typename TF, typename T> 
auto call_with_same_arg(TF&& f, T&& x) 
    -> decltype(helper<TN - 1>{}(std::forward<TF>(f), std::forward<T>(x))) 
{ 
    return helper<TN - 1>{}(std::forward<TF>(f), std::forward<T>(x)); 
} 

使用法:

int add(int a, int b, int c) 
{ 
    return a + b + c; 
} 

int main() 
{ 
    assert(call_with_same_arg<3>(add, 5) == 15); 
} 

live wandbox example


は、ここで同じことの完全なC++ 17の実装です:

template <std::size_t TN, typename TF, typename T> 
decltype(auto) call_with_same_arg(TF&& f, T&& x) 
{ 
    if constexpr(TN == 1) 
    { 
     return f(x); 
    } 
    else 
    { 
     return call_with_same_arg<TN - 1>(
      [&](auto&&... xs){ return f(x, std::forward<decltype(xs)>(xs)...); }, x); 
    } 
} 

live wandbox example

完全のために

、C++ 14の実装:

template <std::size_t TN> 
struct helper 
{ 
    template <typename TF, typename T> 
    decltype(auto) operator()(TF&& f, T&& x) 
    { 
     return helper<TN - 1>{}(
      [&](auto&&... xs){ return f(x, std::forward<decltype(xs)>(xs)...); }, x); 
    } 
}; 

template <> 
struct helper<0> 
{ 
    template <typename TF, typename T> 
    decltype(auto) operator()(TF&& f, T&& x) 
    { 
     return f(x); 
    } 
}; 

template <std::size_t TN, typename TF, typename T> 
decltype(auto) call_with_same_arg(TF&& f, T&& x) 
{ 
    return helper<TN - 1>{}(std::forward<TF>(f), std::forward<T>(x)); 
} 

live wandbox example

+0

は答えをいただき、ありがとうございます。あなたが他のC++標準のための解決策を考えているなら、ここでそれらを書くことが自由になります。私はちょうど(そしてそれは)テンプレートメタプログラミングのトリックであることを示すために、C++ 11を書きました。 –

+0

おお、あなたはちょうどC++ 17バージョンを投稿しました。 C++のためのものと同じものがありますか? –

+0

@ YaroslavKishchenko:少し長くなりますが、C++よりも優れています。それを秒間に投稿します。 –

関連する問題