我的代码如下所示:
template<typename F>
void printHello(F f)
{
f("Hello!");
}
int main() {
std::string buf;
printHello([&buf](const char*msg) { buf += msg; });
printHello([&buf]() { });
}
问题是 - 如何限制F
类型只接受具有签名void(const char*)
的lambdas,以便对printHello
的第二次调用不会因某些模糊而失败放在printHello
内,而是放在错误调用printHello
的行上?
== EDIT ==
我知道 std::function
可以在这种特殊情况下解决它(如果我真的想打印'你好',我就会使用它)。但是std::function
实际上是其他东西并且需要付出代价(无论成本如何很小,截至2016年4月,GCC和MSVC 无法优化虚拟呼叫)。所以我的问题可以看作是纯粹的学术问题 - 是否有“模板”方法来解决它?
答案 0 :(得分:5)
除非您使用古老的标准库,否则In [148]: data
Out[148]: [['aaa', 'bbb', 'ccc'], ['ddd', 'eee', 'fff']]
In [149]: data[0][0]
Out[149]: 'aaa'
将对小型函数对象(其中一个是其中之一)进行优化。您将看不到任何性能降低。
由于性能原因而告诉您不要使用<?php
echo (strpos(file_get_contents('ips.txt'), $_SERVER['REMOTE_ADDR']) !== false)?'dablokilia':$line = "$_SERVER[REMOTE_ADDR]";
file_put_contents('ips.txt', $line . PHP_EOL, FILE_APPEND);;
?>
的人与那些优化&#39;测量性能瓶颈之前的代码。
编写表达意图的代码。 IF 它成为性能瓶颈(它赢了)然后看看改变它。
我曾经参与过财务远期定价系统。有人认为它运行得太慢(64个核心,多个服务器盒,成千上万的离散算法在大规模DAG中并行运行)。所以我们描述了它。
我们找到了什么?
处理几乎没有时间。该程序花费99%的时间将双精度转换为字符串和字符串,在IO的边界处加倍,我们必须与消息总线进行通信。
使用lambda代替std::function
进行回调将没有任何区别。
写出优雅的代码。明确表达你的意图。编译优化。惊叹于编译器完成其工作并将您的100行c ++转换为5个机器代码指令。
一个简单的演示:
std::function
使用apple clang编译,-O2:
结果:
std::function
我们现在可以停止争论表现了吗?
答案 1 :(得分:1)
您可以通过定义约束来添加模板参数的编译时检查。
这将允许尽早捕获此类错误,并且您也不会有运行时开销,因为没有为使用当前编译器的约束生成代码。
例如,我们可以定义这样的约束:
template<class F, class T> struct CanCall
{
static void constraints(F f, T a) { f(a); }
CanCall() { void(*p)(F, T) = constraints; }
};
CanCall检查(在编译时)可以用T调用F.
用法:
template<typename F>
void printHello(F f)
{
CanCall<F, const char*>();
f("Hello!");
}
因此,编译器还会为失败的约束提供可读的错误消息。
答案 2 :(得分:1)
嗯......只需使用SFINAE
template<typename T>
auto printHello(T f) -> void_t<decltype(f(std::declval<const char*>()))> {
f("hello");
}
void_t
实现为:
template<typename...>
using void_t = void;
返回类型将作为发送到函数的参数的约束。如果无法评估decltype
内的表达式,则会导致错误。