c++ - 模板参数不能在隐式构造的参数上推导出来
问题描述
我想在 c++17 中有以下代码:
#include <iostream>
#include <string>
#include <type_traits>
#include <functional>
class Foo;
template<class T>
class Bar {
public:
std::function<T(Foo&)> m_fn;
template<class Fn>
Bar(Fn fn) : m_fn(fn) {};
T thing(Foo &foo) const {
return m_fn(foo);
}
};
template<class Fn>
Bar(Fn) -> Bar<decltype(std::invoke(std::declval<Fn>(),
std::declval<Foo&>()))>;
class Foo {
public:
Foo() {};
template<class T>
std::vector<T> do_thing(const Bar<T> &b) {
std::vector<T> r;
r.push_back(b.thing(*this));
return r;
}
};
std::string test(Foo &) {
return "hello";
}
int main() {
Foo foo = Foo();
// works
std::vector<std::string> s = foo.do_thing(Bar{test});
// cant deduce T parameter to do_thing
std::vector<std::string> s = foo.do_thing({test});
}
但是编译这个给了我“无法在调用do_thing
.如果可能,将其作为参数传递。do_thing(Bar{test})
do_thing({test})
do_thing(test)
Bar
我也不想转发声明要传递给do_thing
任何一个的变量
有什么方法可以指导模板参数的推断,T
以便调用do_thing
可以保持干净?
编辑:
抱歉编辑晚了,但在我包含的示例中,Bar 构造函数的参数过于简化。实际上,有一个额外的参数std::optional<std::string> desc = std::nullopt
,将来可能会改变(尽管不太可能)。所以建造Bar
内部do_thing
会有点难以维护......
解决方案
想要拥有
do_thing({test})
或do_thing(test)
隐式构造 aBar
并将其作为参数传递(如果可能)。
不幸的是,当您调用do_thing({test})
or时do_thing(test)
,test
(或{test}
)不是Bar<T>
对象。所以编译器无法推断T
类型,也无法构造Bar<T>
对象。
一种先有鸡还是先有蛋的问题。
我能想象的最好Foo
的do_test()
方法是在 中添加如下方法
template<typename T>
auto do_thing (T const & t)
{ return do_thing(Bar{t}); }
这样你就可以调用(没有图表)
std::vector<std::string> s = foo.do_thing(test);
你得到相同的结果
std::vector<std::string> s = foo.do_thing(Bar{test});
- 编辑 -
OP问
有什么方法可以保留 {test} 大括号语法吗?也许与 initializer_list 或什么?
是的...与std::initializer_list
template<typename T>
auto do_thing (std::initializer_list<T> const & l)
{ return do_thing(Bar{*(l.begin())}); }
但是,这样,你也接受
std::vector<std::string> s = foo.do_thing(Bar{test1, test2, test3});
仅使用test1
也许更好一点……另一种方法是通过 C 风格的数组
template <typename T>
auto do_thing (T const (&arr)[1])
{ return do_thing(arr[0]); }
这样你只接受一个元素。
推荐阅读
- sql-server - .NET Core API 无法通过 docker-compose 连接到数据库
- moqui - orderby lastUpdatedStamp in entity-find
- database - 实体、实体类型和实体实例之间有什么区别?
- python - 什么是 Python“系统库”?
- python - python docker如何打印脚本的返回码以了解测试脚本是通过还是失败
- python - Flask - 每个 HTTP 请求似乎都不是一个新的独立请求。这是为什么?
- python - Python pathlib:解析符号链接的完整路径而不遵循它
- linux - 是否可以从 x86(x64) windows 交叉编译到 x86(x64) linux?
- amazon-dynamodb - 如何使用带有 dynamodb 的 aws cli 查询名称包含“:”的索引?
- java - 在 JAVA 中使用实际 API 调用模拟测试支付的最佳实践是什么