c++ - 采用 lambda 的模板类的类型推导

标签 c++ templates lambda c++17

我正在尝试编写一个类,它能够在以后及时调用不带参数的 lambda。我期待 C++17 类模板参数推导以避免需要工厂函数。但是,尝试在不指定类型的情况下实例化对象会失败。我可以很好地使用工厂功能,但我想了解为什么会这样。

我使用的是 VC++2017,启用了 C++17 工具集。这是预期的行为吗?为什么?由于模板函数和模板类的类型推导规则不同,是否可以避免或需要工厂函数?我们将不胜感激。

template <typename F>
class WillInvoke
{
public:
    WillInvoke(std::decay_t<F> f) : f(std::move(f)) { }

    void CallNow() { f(); }

private:
    std::decay_t<F> f;
};

template <typename F>
WillInvoke<F> make_WillInvoke(F && f)
{
    return WillInvoke<F>(std::forward<F>(f));
}

int main()
{
    // OK
    auto w = make_WillInvoke([](){ std::cout << "Hello World"; });
    w.CallNow();

    // Won't compile
    WillInvoke w2([](){ std::cout << "Hello World"; }); // No instance of constructor matches argument list
    w2.CallNow();
}

最佳答案

这是因为像 std::decay<T>::type 这样的成员类型别名不可扣除。

template<typename T>
void call_me(std::decay_t<T>) {}

// won't work :(
// call_me(1);

我不认为你的类应该衰减类型。相反,你的类应该声明它需要一个对象类型并将衰减移到 make 函数中:

template <typename F> // requires std::is_object_v<F>
class WillInvoke
{
    static_assert(std::is_object_v<F>,
        "WillInvoke requires F to be an object type"
    );
public:
    WillInvoke(F f) : f(std::move(f)) { }

    void CallNow() { f(); }

private:
    F f;
};

template <typename F>
auto make_WillInvoke(F && f) -> WillInvoke<std::decay_t<F>>
{
    return WillInvoke<std::decay_t<F>>(std::forward<F>(f));
}

好的是,在 C++20 中,您可以取消对要求的注释,让编译器在调用站点强制执行它。

关于c++ - 采用 lambda 的模板类的类型推导,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55715241/

相关文章:

c++ - const 限定符在复制初始化变量时有用吗?

C++:可以在多个文件中调用静态变量吗?

c++ - 如何优化大集合散点的插值?

c++ - 需要一种方法在仅 header 库中拥有任何类型的模板化常量

c++ - 具有多个模板参数包的部分模板特化

c++ - 如何使用模板将 lambda 转换为 std::function

php - 如何在 PHP 中访问运行时创建的函数中的解析错误?

c++ - Windows C++ 在内存中锁定文件

c++11 - 尝试使用 lambda 函数作为 condition_variable 等待方法的谓词

c++ - 只读类变量 (C++) 和运算符重载