检索对象的函数运算符的参数类型
Retrieve argument type of function operator of an object
我有一个包装器,它可以将接受多个参数的函数转换为只接受一个参数的函数(提供了其他参数的值)。此代码适用于 functions:
template <class R, class F, class A0, class A1>
class CMyWrapper {
F m_f;
A0 m_default_a0;
public:
CMyWrapper(F f, const A0 &default_a0)
:m_f(f), m_default_a0(default_a0)
{}
R operator ()(const A1 &a1) const
{
return m_f(m_default_a0, a1);
}
};
template <class R, class A0, class A1>
CMyWrapper<R, R (*)(const A0&, const A1&), A0, A1>
SupplyConstArg(R (*fun)(const A0&, const A1&), const A0 &default_a0)
{
return CMyWrapper<R, R (*)(const A0&, const A1&), A0, A1>(fun, default_a0);
}
double MyFunc(const double &x, const double &y); // some function
所以现在我可以做,例如SupplyConstArg(MyFunc, 1.23)(4.56)
调用 MyFunc(1.23, 4.56)
(此表达式的左侧部分是一个函数对象,它提供常量第一个参数)。到目前为止一切顺利。
但是,我在为 函数对象 而不是函数编写类似函数时遇到了一些困难(出于性能原因,我希望尽可能避免使用函数指针)。假设:
struct CMyFunObj {
double operator ()(const double &x, const double &y);
};
我的问题是 在给定此类函数对象 的实例的情况下,如何匹配 return 类型或参数类型?到目前为止,我想出了:
template <class F, class R, class A0, class A1>
R Infer(F f, R (F::*fun)(const A0 &a0, const A1 &a1) = &F::operator ());
哪种方法有效,但前提是还指定了第二个参数,例如通过调用:
Infer(CMyFunObj(), &CMyFunObj::operator ());
但如果我省略第二个参数并依赖默认值则不会。知道如何在 C++03 中做到这一点吗?
我不确定我是否理解了问题,但你的意思可能是这样的?
struct X {};
struct Y {};
template <class R, class A0, class A1, class F, R(F::*)(const A0 &, const A1 &) = &F::operator()>
void Infer(F f) { }
struct S {
void operator()(const X &, const Y &) { }
void foo(const X &, const Y &) { }
};
int main() {
Infer<void, X, Y>(S{});
Infer<void, X, Y, S, &S::foo>(S{});
}
根据评论,这应该适用于 C++03:
struct X {};
struct Y {};
template <class R, class A0, class A1, class F>
void Infer(F f, R(F::*ptr)(const A0 &, const A1 &)) { (f.*ptr)(A0(), A1()); }
template<class F>
void Infer(F f) {
Infer(f, &F::operator());
}
struct S {
void operator()(const X &, const Y &) { }
void foo(const int &, const char &) { }
};
int main() {
Infer(S());
Infer(S(), &S::foo);
}
这样,您既可以指定要调用的方法,也可以依赖将其作为参数显式推送的中间函数。
你可以简单地使用一个中间函数:
template <class F, class R, class A0, class A1>
void Infer(F f, R (F::*fun)(const A0 &a0, const A1 &a1));
template <class F>
void Infer(F f) {
Infer(f, &F::operator());
}
Infer(CMyFunObj());
如果你需要推断类型,你可以,如果你不想修改你的函子,你可以使用外部帮助class:
template <class U>
struct result_type;
template <typename F>
typename result_type<F>::type Infer(F f) {
return Infer(f, &F::operator());
}
然后:
struct CMyFunObj {
double operator ()(const double& x, const double& y) { return x + y; }
};
template <>
struct result_type<CMyFunObj> {
typedef double type;
};
在 C++03 中,你不能真正推断出类型(除非你想像 typeof
那样使用),所以你必须实际提供它:
struct CMyFunObj {
typedef double result_type;
double operator()(const double &x, const double &y);
};
现在您可以使用这些额外的信息了:
template <class F, class A0>
CMyWrapper<typename F::result_type, F, A0>
SupplyConstArg(F f, A0 const& a0) {
return CMyWrapper<typename F::result_type, F, A0>(f, a0);
}
SupplyConstArg(CMyFunObj(), 4.0)(5.0);
您不需要 CMyWrapper
中的类型 A1
,它可以是其 operator()
上的模板参数。
我有一个包装器,它可以将接受多个参数的函数转换为只接受一个参数的函数(提供了其他参数的值)。此代码适用于 functions:
template <class R, class F, class A0, class A1>
class CMyWrapper {
F m_f;
A0 m_default_a0;
public:
CMyWrapper(F f, const A0 &default_a0)
:m_f(f), m_default_a0(default_a0)
{}
R operator ()(const A1 &a1) const
{
return m_f(m_default_a0, a1);
}
};
template <class R, class A0, class A1>
CMyWrapper<R, R (*)(const A0&, const A1&), A0, A1>
SupplyConstArg(R (*fun)(const A0&, const A1&), const A0 &default_a0)
{
return CMyWrapper<R, R (*)(const A0&, const A1&), A0, A1>(fun, default_a0);
}
double MyFunc(const double &x, const double &y); // some function
所以现在我可以做,例如SupplyConstArg(MyFunc, 1.23)(4.56)
调用 MyFunc(1.23, 4.56)
(此表达式的左侧部分是一个函数对象,它提供常量第一个参数)。到目前为止一切顺利。
但是,我在为 函数对象 而不是函数编写类似函数时遇到了一些困难(出于性能原因,我希望尽可能避免使用函数指针)。假设:
struct CMyFunObj {
double operator ()(const double &x, const double &y);
};
我的问题是 在给定此类函数对象 的实例的情况下,如何匹配 return 类型或参数类型?到目前为止,我想出了:
template <class F, class R, class A0, class A1>
R Infer(F f, R (F::*fun)(const A0 &a0, const A1 &a1) = &F::operator ());
哪种方法有效,但前提是还指定了第二个参数,例如通过调用:
Infer(CMyFunObj(), &CMyFunObj::operator ());
但如果我省略第二个参数并依赖默认值则不会。知道如何在 C++03 中做到这一点吗?
我不确定我是否理解了问题,但你的意思可能是这样的?
struct X {};
struct Y {};
template <class R, class A0, class A1, class F, R(F::*)(const A0 &, const A1 &) = &F::operator()>
void Infer(F f) { }
struct S {
void operator()(const X &, const Y &) { }
void foo(const X &, const Y &) { }
};
int main() {
Infer<void, X, Y>(S{});
Infer<void, X, Y, S, &S::foo>(S{});
}
根据评论,这应该适用于 C++03:
struct X {};
struct Y {};
template <class R, class A0, class A1, class F>
void Infer(F f, R(F::*ptr)(const A0 &, const A1 &)) { (f.*ptr)(A0(), A1()); }
template<class F>
void Infer(F f) {
Infer(f, &F::operator());
}
struct S {
void operator()(const X &, const Y &) { }
void foo(const int &, const char &) { }
};
int main() {
Infer(S());
Infer(S(), &S::foo);
}
这样,您既可以指定要调用的方法,也可以依赖将其作为参数显式推送的中间函数。
你可以简单地使用一个中间函数:
template <class F, class R, class A0, class A1>
void Infer(F f, R (F::*fun)(const A0 &a0, const A1 &a1));
template <class F>
void Infer(F f) {
Infer(f, &F::operator());
}
Infer(CMyFunObj());
如果你需要推断类型,你可以
template <class U>
struct result_type;
template <typename F>
typename result_type<F>::type Infer(F f) {
return Infer(f, &F::operator());
}
然后:
struct CMyFunObj {
double operator ()(const double& x, const double& y) { return x + y; }
};
template <>
struct result_type<CMyFunObj> {
typedef double type;
};
在 C++03 中,你不能真正推断出类型(除非你想像 typeof
那样使用),所以你必须实际提供它:
struct CMyFunObj {
typedef double result_type;
double operator()(const double &x, const double &y);
};
现在您可以使用这些额外的信息了:
template <class F, class A0>
CMyWrapper<typename F::result_type, F, A0>
SupplyConstArg(F f, A0 const& a0) {
return CMyWrapper<typename F::result_type, F, A0>(f, a0);
}
SupplyConstArg(CMyFunObj(), 4.0)(5.0);
您不需要 CMyWrapper
中的类型 A1
,它可以是其 operator()
上的模板参数。