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) {
// ...
}