Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.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++_Templates - Fatal编程技术网

C++ 使用std::function作为参数的构造函数模板参数推断

C++ 使用std::function作为参数的构造函数模板参数推断,c++,templates,C++,Templates,我有一个带有模板构造函数的类,如下所示: class Foo { private: std::unordered_map<std::type_index, std::vector<std::function<void(BaseT*)>>> funcs; public: template<class T> Foo(const std::function<void(T* arg)>& func) {

我有一个带有模板构造函数的类,如下所示:

class Foo {
private:

    std::unordered_map<std::type_index, std::vector<std::function<void(BaseT*)>>> funcs;

public:

    template<class T> Foo(const std::function<void(T* arg)>& func) {
        auto funcToStore = [func](BaseT* a) { func(static_cast<T*>(a)); };
        this->funcs[std::type_index(typeid(T))].push_back(funcToStore);
    }

}
省略显式的
也不起作用,因为无法从lambda参数类型推导模板参数

因此,一种解决方案是将lambda包装在
std::function
对象中:

Foo* foo = new Foo(std::function<void(MyT*)>([](MyT* arg) { ... }));
这更短,当在lambda参数中使用
auto
关键字时,我必须只指定一次实际类型
MyT
,因此这最终似乎是一个不错的解决方案

但还有其他更简短的解决方案吗?这样就没有必要把lambda包起来了?比如:

Foo* foo = new Foo([](MyT* arg) { ... });

使用普通模板参数而不是
std::function

template<class T> using Func = std::function<void(T*)>;

Foo* foo = new Foo(Func<MyT>([](MyT* arg) { ... }));
class Foo {
    std::unordered_map<size_t, std::vector<BaseT*>> funcs;

public:
    template<class T> Foo(const T& func) {
        // ...
    }

};
当然,如果您想支持函数类型的所有可能情况,您需要

现在,您可以根据需要提取参数类型甚至返回类型:

template<class T> Foo(const T& func) {
    using Arg = std::tuple_element_t<0, typename  function_traits<T>::arguments>;
    auto funcToStore = [func](BaseT* a) { func(static_cast<Arg>(a)); };

    funcs[typeid(Arg).hash_code()].push_back(funcToStore);
}
然后像这样使用约束:

template<class T, std::enable_if_t<is_valid_foo_function<T>::value>* = nullptr>
Foo(const T& func) {
    // ...
}
模板
Foo(const T&func){
// ...
}

@StoryTeller:说得好,我更新了问题!当我想将传递的函数存储在一个向量中时,这会起作用吗?很抱歉,原来的问题中有一些错误,因为存储函数的部分出错了。我更新了这个。您可以存储
std::function
的向量,但在构造函数中接收
const T&
。@csk我更新了示例,以更接近地反映您最初的操作。
template<class T> Foo(const T& func) {
    using Arg = std::tuple_element_t<0, typename  function_traits<T>::arguments>;
    auto funcToStore = [func](BaseT* a) { func(static_cast<Arg>(a)); };

    funcs[typeid(Arg).hash_code()].push_back(funcToStore);
}
template<typename T>
using is_valid_foo_function = std::is_convertible<
    BaseT*, // form
    std::tuple_element_t<0, typename function_traits<T>::arguments> // to
>;
template<class T, std::enable_if_t<is_valid_foo_function<T>::value>* = nullptr>
Foo(const T& func) {
    // ...
}