从其他文件使用sfinae的正确方法是什么?

时间:2019-06-20 16:29:27

标签: c++ c++17 sfinae

在Jarod使用this给出的令人惊奇的答案之后,我使用SFINAE来使函数包装器的行为根据函数的返回类型而有所不同,我很难将其合并到数据结构的代码中:

代码结构

名为 utils 的目录包含4以下文件:

+ utils
| ---> wrap.hpp
| ---> wrap.cpp
| ---> exec.hpp
| ---> exec.cpp

这些文件包含要在main内部使用的实用程序逻辑。

  • exec处理解析std::vector<std::string>的令牌;一组单词一起构成一个命令,该命令通过调用具有相关自变量的相关结构的函数来解释。

    1. 标头包含一个结构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);
  1. .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包含与包装函数有关的实际逻辑:

    1. 标题包含定义:
// 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>;
  1. .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 /模板的东西。

实现此包装器功能的正确方法是什么,同时,如果可能的话,将代码拆分成多个文件以得到更好的代码结构和模块化/可扩展性?

0 个答案:

没有答案