g
関数ポインター、ファンクター、またはラムダを、渡された関数の引数の型を使用するテンプレート関数に渡す方法を探しています。次に例を示します。
template<class T1, class T2, class T3>
struct wrapper_t {
boost::function<void(T1,T2,T3)> f;
wrapper_t( boost::function<void(T1,T2,T3)> f ) : f(f) {}
void operator( std::vector<T1> &a, std::vector<T2> &b, T3 c ) {
assert(a.size() == b.size());
for(size_t i = 0 ; i != a.size() ; i++) f(a[i], b[i], c);
}
};
template<class T1, class T2, class T3>
wrapper_t<T1,T2,T3> make_wrapper( boost::function<void(T1,T2,T3)> f ) {
return wrapper_t<T1,T2,T3>( f );
}
void f(int, double, char) {};
wrapper_t<int, double, char> w0(f); // need to repeat types
auto w1 = make_wrapper(f); // more comfortable
std::vector<int> a{{1, 2, 3}};
std::vector<double> b{{1.0, 2.0, 3.0}};
w0( a, b, 'c' );
w1( a, b, 'c' );
このmake_wrapper
関数は、引数から型を抽出するためだけに存在し、型を 2 回入力する必要がないようにするための構文糖衣です。
私の問題の最小限の例は、次の関数です。
template<class T>
void g1( const boost::function<void(T)> & ) {}
これらを入力として使用する
void f1(int) {}
struct f2_t { void operator()(int) {} };
それは推論に失敗しますT=int
f2_t f2;
g1( f1 ); // mismatched types ‘const std::function<void(T)>’ and ‘void(int)’
g1( f2 ); // ‘f2_t’ is not derived from ‘const std::function<void(T)>’
g1( [](int){} ); // ‘::<lambda(int)>’ is not derived from ‘…
g1<int>( f1 ); // ok
g1<int>( f2 ); // ok
g1<int>( [](int){} ); // ok
ただしT=int
、単純な関数ポインターから推測できますが、これはファンクターまたはラムダでも機能しません。
template<class T>
void g2( void (*)(T) ) {}
g2( f1 ); // ok
g2( f2 ); // mismatched types …
g2<int>( f2 ); // ok
g2( [](int){} ); // mismatched types …
g2<int>( [](int){} ); // ok
T
単純な関数ポインターだけでなく、ファンクターとラムダも推論する方法はありますか?
それとも、このようなものでなければなりませんか?
template<class F>
void g( F ) { typedef first_argument_of<F>::type T; }
(私の実際のコードでは、このように 4 つの引数を持つ関数を分解する必要がありますstd::function::…argument_type
が、1 つまたは 2 つの引数に対してしか存在しませboost::function
ん。上記などを参照)F
function