创建并调用一个空函数

时间:2019-02-26 15:43:40

标签: c++ function templates

给出一个函数签名(例如来自A 23.03.2018 08:17:00 A 23.03.2018 08:18:00 A 23.03.2018 08:19:00 A 23.03.2018 08:20:00 .... A 23.03.2018 13:55:00 B 23.03.2018 11:17:00 B 23.03.2018 11:18:00 B 23.03.2018 11:19:00 B 23.03.2018 11:20:00 .... B 23.03.2018 13:55:00 参数),我想用该签名创建一个(非内联的)函数,然后调用它。

以下内容应阐明此意图。按照编写的方式,它是无效的,因为标记的行实际上会生成一个空函数指针,而不是空函数:

template

如何在此处创建函数对象?


(旁注:这似乎很奇怪。原因是它是一个通用分析器,它调用{标记为不可内联的)测试函数template <typename Function, typename... Args> void foo(Args... args) { Function fn_trivial = {}; //incorrect; should be empty function, not null function fn_trivial(args...); } 次来计算平均延迟。可以通过减去具有相同参数的函数调用的延迟(平均而言不执行任何操作)来获得(更好的)测试代码成本。)

1 个答案:

答案 0 :(得分:1)

您不能在C ++中创建本地函数。您可以创建本地对象类型并定义/调用其operator(),也可以使用lambda,但此时最好将其作为真实函数放在外面:

template <typename TypeRet, typename... Args>
TypeRet empty_function(Args... args) {
    return TypeRet();
}

template <typename Function, typename... Args>
void foo(Args... args) {
    empty_function<decltype( std::declval<Function>()(args...) )>(args...);
}

(请根据需要考虑添加std::forward。)

请注意,即使标记为不可内联的,任何有价值的编译器也会删除该调用。这是因为即使未内联函数,它也不会执行任何操作,因此可以完全删除。您可以通过多种方式解决此问题,但是使用volatile变量可移植到Clang,GCC,ICC和MSVC:

#ifdef _MSC_VER
    #define NOINLINE __declspec(noinline)
#else
    #define NOINLINE __attribute__((noinline))
#endif
template <typename TypeRet, typename... Args>
NOINLINE TypeRet empty_function(Args... args) {
    TypeRet volatile a = TypeRet();
    return a;
}

See it live.