在Jarod使用this给出的令人惊奇的答案之后,我使用SFINAE来使函数包装器的行为根据函数的返回类型而有所不同,我很难将其合并到数据结构的代码中:
代码结构:
名为 utils 的目录包含4
以下文件:
+ utils
| ---> wrap.hpp
| ---> wrap.cpp
| ---> exec.hpp
| ---> exec.cpp
这些文件包含要在main
内部使用的实用程序逻辑。
exec
处理解析std::vector<std::string>
的令牌;一组单词一起构成一个命令,该命令通过调用具有相关自变量的相关结构的函数来解释。
command
,该结构知道它包含多少个单词,并保存单词本身以及execute
函数定义:typedef struct command
{
uint8_t tokens_count;
vector<string> tokens;
command() : tokens_count(0U) { tokens.resize(4); }
}command;
// More on this function below.
void execute (command c);
.cpp
基本上是对命令进行解析的大条件检查,如下所示:void execute(command c)
{
switch (c.tokens_count)
{
// If the command consists of two words,
// It's one of the following:
case 2U:
if (c.tokens[0] == "GETSIZE")
{
if (c.tokens[1] == "MINHEAP")
{
// GETSIZE MINHEAP
auto out = wrapper([&](){ return minheap.getSize();});
}
else if (c.tokens[1] == "MAXHEAP")
{
// GETSIZE MAXHEAP
auto out = wrapper([&](){ return maxheap.getSize();});
}
else if (c.tokens[1] == "AVLTREE")
{
// GETSIZE AVLTREE
auto out = wrapper([&](){ return avl.getSize();});
}
// more stuff like these
接下来,是包装器:
wrap
包含与包装函数有关的实际逻辑:
// remember to go and
// check my initial question @
// https://stackoverflow.com/questions/56685232/problems-trying-to-construct-a-wrapper-measuring-function-call-time
// to understand more about the logic behind the wrapper.
template<typename F, typename... Args>
auto wrapper(F function, Args&&... args) noexcept
-> std::enable_if_t<std::is_same<void, std::invoke_result_t<F, Args&&...>>::value, output>;
template<typename F, typename... Args>
auto wrapper(F function, Args&&... args) noexcept
-> std::enable_if_t<!std::is_same<void, std::invoke_result_t<F, Args&&...>>::value, output>;
.cpp
实现:template<typename F, typename... Args>
auto wrapper(F function, Args&&... args) noexcept
-> std::enable_if_t<std::is_same<void, std::invoke_result_t<F, Args&&...>>::value, output>
{
const high_resolution_clock::time_point t1 = timeNow();
function(forward<Args>(args)...);
const auto elapsed = duration(timeNow() - t1);
output out;
out.time = elapsed;
out.result = "";
return out;
}
template<typename F, typename... Args>
auto wrapper(F function, Args&&... args) noexcept
-> std::enable_if_t<!std::is_same<void, std::invoke_result_t<F, Args&&...>>::value, output>
{
const high_resolution_clock::time_point t1 = timeNow();
auto result = function(forward<Args>(args)...);
const auto elapsed = duration(timeNow() - t1);
output out;
out.time = elapsed;
out.result = to_string(result);
return out;
}
但是,事实证明,这绝对不是做SFINAE魔术的方法:
In file included from util/exec.cpp:2:
util/wrap.hpp:55:6: error: function 'wrapper<(lambda at util/exec.cpp:38:25)>' is used but not defined in this translation unit, and cannot be defined in any other translation unit because its type does not have linkage
auto wrapper(F function, Args&&... args) noexcept
^
util/exec.cpp:38:17: note: used here
auto out = wrapper([&](){ return minheap.getSize();});
我走了过去,做了强制性的Google(或DDG)-fu,但没有发现任何特别涉及SFINAE /模板的东西。
实现此包装器功能的正确方法是什么,同时,如果可能的话,将代码拆分成多个文件以得到更好的代码结构和模块化/可扩展性?