我正在尝试在对象中实现“emplace”功能。它的结构如下。我有一个模板对象,它将size_t与模板类型相结合。我希望能够在std库容器中构建它,例如向量。我没有使用std::pair
,因为我的班级B
将围绕数据提供其他功能。
我如何修改代码,以便我可以像在主要的那样调用emplace?
#include <iostream>
#include <vector>
using namespace std;
class C {
public:
C(const string& _s) : s(_s) {}
C(string&& _s) : s(_s) {}
private:
string s;
};
template<typename A>
class B {
public:
B(size_t _i, const A& _a) : i(_i), a(_a) {}
B(size_t _i, A&& _a) : i(_i), a(_a) {}
private:
size_t i;
A a;
};
int main() {
vector<B<C>> v;
v.emplace_back(5, "Hello");
}
答案 0 :(得分:2)
这不起作用的原因不是因为您无法进行隐式转换。在以下代码中:
vector<B<C>> v;
v.emplace_back(5, "Hello");
emplace_back
完美转发到v
包含的类型的构造函数,即B<C>
。所以我们最终调用了(它实际上通过分配器发生,但让我们忽略了细节):
B<C>(5, "Hello")
为什么这不起作用?您经常听到有人说您在调用模板时无法进行隐式转换;这是松散的。但B<C>
的构造函数不是模板; B
是一个已经模板化的模板类,因此B<C>
是一个普通类,其构造函数不是模板。因此隐式转换是允许的。
但是,C ++中的隐式转换包括:
(http://en.cppreference.com/w/cpp/language/implicit_conversion)。
用户定义的转换基本上是定义隐式构造函数或转换运算符的类。 string
可能是标准库的一部分,但它只是一个普通的类,从const char*
到string
的转换已经算作用户转换。因此,您无法从string
获得第二个。
解决此问题的一种方法是为C构建构造函数的模板,但单个参数隐式模板构造函数可以打开各种其他问题。我可能只是定义了第二个带const char*
的构造函数。在cppcon,btw:https://www.youtube.com/watch?v=PNRju6_yn3o完全就这个问题进行了全面的讨论。
答案 1 :(得分:1)
每个参数允许一个用户定义的转换序列,你有两个:
const char*
- &gt; std::string
std::string
- &gt; C
您可以通过实施通用转发构造函数来减少隐式转换的数量:
template<typename A>
class B {
public:
template<typename X>
B(size_t _i, X&& _a) : i(_i), a(std::forward<X>(_a)) {}
...
};
这将生成一个完美匹配B(size_t, const char*)
的构造函数emplace_back(5, "Hello")
,只需一次转换即可a
构建const char *
。