web-dev-qa-db-ja.com

テンプレート引数リストでテンプレート関数を渡す方法

template関数があるとします。

template<typename T>
T produce_5_function() { return T(5); }

このtemplate全体を別のtemplateに渡すにはどうすればよいですか?

produce_5_functionは関手でした、問題はありません:

template<typename T>
struct produce_5_functor {
  T operator()() const { return T(5); }
};
template<template<typename T>class F>
struct client_template {
  int operator()() const { return F<int>()(); }
};
int five = client_template< produce_5_functor >()();

しかし、私は生の関数テンプレートでこれを実行できるようにしたいです:

template<??? F>
struct client_template {
  int operator()() const { return F<int>(); }
};
int five = client_template< produce_5_function >()();

答えは「これはできない」だと思います。

答えは「これはできない」だと思います。

はい、その場合、関数テンプレートをテンプレート引数として渡すことはできません。 14.3.3から:

テンプレートtemplate-parameterのtemplate-argumentは、クラステンプレートまたはエイリアステンプレートの名前であり、id-expressionとして表されます。

テンプレート関数はインスタンス化する必要がありますbefore他のテンプレートに渡します。考えられる解決策の1つは、次のように静的produce_5_functionを保持するクラス型を渡すことです。

template<typename T>
struct Workaround {
  static T produce_5_functor() { return T(5); }
};
template<template<typename>class F>
struct client_template {
  int operator()() const { return F<int>::produce_5_functor(); }
};
int five = client_template<Workaround>()();

エイリアステンプレートを使用すると、もう少し近づくことができます。

template <typename T>
T produce_5_functor() { return T(5); }

template <typename R>
using prod_func = R();

template<template<typename>class F>
struct client_template {
  int operator()(F<int> f) const { return f(); }
};

int five = client_template<prod_func>()(produce_5_functor);
16
Jesse Good

その関数をラップするのはどうですか?

template<typename T>
struct produce_5_function_wrapper {
    T operator()() const { return produce_5_function<T>(); }
};

次に、関数の代わりにラッパーを使用できます。

int five = client_template< produce_5_function_wrapper >()();

テンプレート関数だけでは動作せず、「テンプレートテンプレート関数」などはありません。

2
mfontanini