Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/134.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 从std::function参数类型推断模板参数_C++_C++20 - Fatal编程技术网

C++ 从std::function参数类型推断模板参数

C++ 从std::function参数类型推断模板参数,c++,c++20,C++,C++20,为什么下面的类A无法在下面的代码中推断其模板参数: #include <functional> template <class... Ts> class A { public: using Func = std::function<void(std::decay_t<Ts>...)>; A(Func func) : m_func(func) { } private: Func m_func; };

为什么下面的类
A
无法在下面的代码中推断其模板参数:

#include <functional>

template <class... Ts>
class A
{
public:

    using Func = std::function<void(std::decay_t<Ts>...)>;

    A(Func func) : m_func(func)
    {
    }

private:

    Func m_func;
};

int main()
{
    //compiles
    A<int, bool> a([](int, bool) {});

    //does not compile with error 'class template argument deduction failed'
    A b([](int, bool) {});

    return 0;
}

模板参数推断传统上是函数调用表达式的独有特性。在C++17中引入之前,类模板的模板参数无法从构造函数调用中推导出来。这样,您就可以显式地指定如何从构造函数调用推导类的模板参数

template <class... Ts>
class A
{
public:

    using Func = std::tuple<Ts...>;

    constexpr A(Func func) : m_func(func)
    {
    }

private:

    Func m_func;
};

template< class... Ts >
A(std::tuple< Ts... >) -> A< Ts... >;

int main()
{
    std::tuple<int, bool> t;
    
    A<int, bool> a(t);

    A b(t); // deduces int, bool types from t

    return 0;
}
两个问题

  • 隐式转换(从lambda到
    std::function
    )在中不被考虑;这导致扣除失败

  • std::decay\u t
    的存在导致:;那么就不能推断出
    Ts

  • 编译以下代码

    #include <functional>
    
    template <class... Ts>
    class A
    {
    public:
    
        using Func = std::function<void(Ts...)>;
    
        A(Func func) : m_func(func)
        {
        }
    
    private:
    
        Func m_func;
    };
    
    int main()
    {
        //compiles
        A<int, bool> a([](int, bool) {});
    
        //compiles
        A b(std::function([](int, bool) {}));
    
        return 0;
    }
    
    #包括
    模板
    甲级
    {
    公众:
    使用Func=std::function;
    A(Func Func):m_Func(Func)
    {
    }
    私人:
    Func mu Func;
    };
    int main()
    {
    //汇编
    A([](int,bool){});
    //汇编
    A b(std::function([](int,bool){});
    返回0;
    }
    
    您认为这个问题被称为“不可推断的上下文”?您的模板实例化需要推断一个类型,该类型在通过
    std::decation\t
    转换后产生模板实例化中使用的类型。那是无法推断的。因为lambda只是一个匿名类,所以也没有办法推断出类似的东西。@SamVarshavchik我想
    std::function
    的推断指南可以得到somewhere@SamVarshavchik是的,
    std::tuple
    优于
    std::function
    ,请参见EDIT1,删除std::decation\t没有帮助。这是个好消息,但您的问题到底是什么?正如我提到的,lambda也变成了匿名闭包。CTAD依赖于演绎指南。而那些推断出的东西就像旧的函数模板一样。从lambda推导
    std::function
    的问题已经被重新讨论过了。例如,
    std::function([](int,bool){})
    无法编译,因为它无法推断
    std::function
    @AndreySemashev的模板参数?CTAD对它有效。那真的很酷!另外,你关于非推断上下文的第二点是不正确的,因为在使用
    std::detaction\t
    的地方,没有模板参数推断在第一位生效。@Andreyesmashev抱歉,我不能理解你的意思;如果不删除
    std::decay\t
    的部分,则即使将
    std::function
    显式传递给构造函数,代码也不会编译。您的意思是使用
    std::decation\t
    会导致由于其他原因而无法编译?
    template< class R, class... Ts >
    A(R (*)(Ts...)) -> A< Ts... >;
    
    #include <functional>
    
    template <class... Ts>
    class A
    {
    public:
    
        using Func = std::function<void(Ts...)>;
    
        A(Func func) : m_func(func)
        {
        }
    
    private:
    
        Func m_func;
    };
    
    int main()
    {
        //compiles
        A<int, bool> a([](int, bool) {});
    
        //compiles
        A b(std::function([](int, bool) {}));
    
        return 0;
    }