是的,另一个由 C++ 术语的随机序列组成的问题标题!
通常我们通过实现来创建一个类 Callable operator()
。但是您也可以通过实现用户定义的到函数指针或引用类型的转换来做到这一点。转换函数可以返回一个指向函数的指针,而不是使用完美转发,然后使用原始参数列表调用该函数。
struct call_printf {
typedef int printf_t( char const *, ... );
operator printf_t & () { return std::printf; }
};
据我所知,typedef
以上是语法必要性。转换函数的名称由type-specifier-seq组成,它不允许像int (*)()
. 那将需要一个abstract-declarator。大概原因是这样的类型名称变得复杂,并且用作对象名称的复杂结构很难解析。
转换函数也可以被模板化,但必须推导出模板参数,因为没有明确指定它们的地方。(这会破坏隐式转换的全部意义。)
问题 #1:在 C++03 中,没有办法指定函数转换运算符模板吗?似乎没有办法以可接受的函数指针类型解析模板参数(即,在推断的上下文中命名它们)。
这是来自 C++11 的等效参考,§13.3.1.1.2/2 [over.call.object]。它与 C++03 基本相同:
另外,对于每一个在 T 中声明的非显式转换函数的形式
operator conversion-type-id () cv-qualifier attribute-specifier-seqopt;
其中cv-qualifier与 cv 具有相同的 cv-qualification 或比 cv 更大的 cv-qualification,其中conversion - type-id表示类型“指向 (P1,...,Pn) 返回 R 的函数的指针”,或类型“对 (P1,...,Pn) 返回 R 的函数的指针的引用”,或类型“对 (P1,...,Pn) 返回 R 的函数的引用”,代理调用函数唯一名称调用函数并具有形式
R call-function ( conversion-type-id F, P1 a1, ... ,Pn an) { return F (a1,... ,an); }
也被认为是候选函数。类似地,代理调用函数被添加到 T 的基类中声明的每个非显式转换函数的候选函数集,前提是该函数没有被另一个中间声明隐藏在 T 中。
问题 #2:在 C++11 中,可以使用默认模板参数指定这样的转换吗?这对 SFINAE 很有用。这里与上面示例的唯一区别是conversion-type-id仅表示实例化后的函数引用,因为它是依赖类型(尽管具有不变性)。这会使 GCC 跳闸并跳过成员模板。
enum { call_alternate = true; }
struct call_switch {
template< bool en = call_alternate >
operator typename std::enable_if< en, decltype( fn_1 ) & >::type ()
{ return fn_1; }
template< bool en = ! call_alternate >
operator typename std::enable_if< en, decltype( fn_2 ) & >::type ()
{ return fn_2; }
};
我们也有别名模板。process
给定第 14.5.7/2 节中的示例,其中冲突声明似乎在实例化之前发生了别名替换。在 GCC 4.7 中,此代码至少实例化了声明,但随后会产生一个奇怪的“候选人需要 2 个参数,提供 2 个”错误。
template< typename t >
using fn_t = void (&)( t );
struct talk {
template< typename t >
operator fn_t< t >() { return fn; }
};
int main() {
talk()( 3 );
}