无法将字符串文字分配给盒装 std::string 向量
Can't assign string literal to boxed std::string vector
这是我的类型系统的简化版本:
#include <string>
#include <vector>
template<typename T>
class Box {
public:
Box(const T& value) : _value(value) {};
private:
T _value;
/* ... */
};
typedef Box<int> Int;
typedef Box<double> Double;
typedef Box<std::string> String;
int main(int argc, char* argv[]) {
String a("abc");
std::vector<String> b = { std::string("abc"), std::string("def") };
// error C2664: 'Box<std::string>::Box(const Box<std::string> &)' : cannot convert argument 1 from 'const char' to 'const std::string &'
std::vector<String> c = { "abc", "def" };
}
虽然 a
和 b
编译,但 c
不编译,原因似乎是我尝试从 const char
初始化。这就提出了两个问题:
为什么 b
可以而不是 c
?是因为std::vector<Box<std::string> >
中的嵌套模板吗?
我可以在不破坏通用装箱机制的情况下使c
工作吗(参见typedef Box<double> Double
?
c
目前需要 2 次隐式用户转换(const char [N]
-> std::string
-> String
),而只允许一次。
您可以将模板构造函数添加到 Box
template<typename T>
class Box {
public:
Box() = default;
Box(const Box&) = default;
Box(Box&&) default;
~Box() = default;
Box& operator=(const Box&) = default;
Box& operator=(Box&&) = default;
template <typename U0, typename ...Us,
std::enable_if_t<std::is_constructible<T, U0, Us...>::value
&& (!std::is_same<Box, std::decay_t<U0>>::value
|| sizeof...(Us) != 0)>* = nullptr>
Box(U0&& u0, Us&&... us) : _value(std::forward<U0>(u0), std::forward<Us>(us)...) {}
private:
T _value;
/* ... */
};
您可以使用创建相应类型的辅助函数:
template <typename T,typename R>
Box<T> make_boxed(const R& value){
return Box<T>(value);
}
必须指定 T
似乎更复杂,另一方面,您可以使用 auto
作为返回类型。完整示例:
#include <string>
template<typename T>
class Box {
public:
Box(const T& value) : _value(value) {};
private:
T _value;
/* ... */
};
typedef Box<std::string> String;
int main(int argc, char* argv[]) {
auto a = make_boxed<std::string>("asd");
}
仅在主要功能部分查看您的源代码:
int main(int argc, char* argv[]) {
String a("abc");
std::vector<String> b = { std::string("abc"), std::string("def") };
// error C2664: 'Box<std::string>::Box(const Box<std::string> &)' :
// cannot convert argument 1 from 'const char' to 'const std::string &'
std::vector<String> c = { "abc", "def" };
}
你的第一行代码:
String a("abc");
正在使用 Box<std::string>
的 typedef
版本,此 class 模板采用 const T&
,因为此版本的模板需要 std::string
它使用 std::string's
构造函数从 const char[3]
构造一个 std::string
,这没问题。
你的下一行代码:
std::vector<String> b = { std::string("abc"), std::string("def") };
是同上的std::vector<T>
。所以这也适用,因为您正在使用有效的 std::string
对象初始化 vector<T>
。
在你的最后一行代码中:
std::vector<String> c = { "abc", "def" };
这里你将 c
声明为 vector<T>
,其中 T
是 Box<std::string>
的 typedef
版本,但是你没有初始化 std::vector<T>
与 Box<std::string>
类型。您正在尝试使用 const char[3]
对象或字符串文字对其进行初始化。
您可以尝试对第三行执行此操作:我没有尝试编译它,但我认为它应该可以工作。
std::vector<String> c = { String("abc"), String("def") };
EDIT -- 我打算使用 String
的构造函数而不是 std::string
进行适当的编辑。
这是我的类型系统的简化版本:
#include <string>
#include <vector>
template<typename T>
class Box {
public:
Box(const T& value) : _value(value) {};
private:
T _value;
/* ... */
};
typedef Box<int> Int;
typedef Box<double> Double;
typedef Box<std::string> String;
int main(int argc, char* argv[]) {
String a("abc");
std::vector<String> b = { std::string("abc"), std::string("def") };
// error C2664: 'Box<std::string>::Box(const Box<std::string> &)' : cannot convert argument 1 from 'const char' to 'const std::string &'
std::vector<String> c = { "abc", "def" };
}
虽然 a
和 b
编译,但 c
不编译,原因似乎是我尝试从 const char
初始化。这就提出了两个问题:
为什么
b
可以而不是c
?是因为std::vector<Box<std::string> >
中的嵌套模板吗?我可以在不破坏通用装箱机制的情况下使
c
工作吗(参见typedef Box<double> Double
?
c
目前需要 2 次隐式用户转换(const char [N]
-> std::string
-> String
),而只允许一次。
您可以将模板构造函数添加到 Box
template<typename T>
class Box {
public:
Box() = default;
Box(const Box&) = default;
Box(Box&&) default;
~Box() = default;
Box& operator=(const Box&) = default;
Box& operator=(Box&&) = default;
template <typename U0, typename ...Us,
std::enable_if_t<std::is_constructible<T, U0, Us...>::value
&& (!std::is_same<Box, std::decay_t<U0>>::value
|| sizeof...(Us) != 0)>* = nullptr>
Box(U0&& u0, Us&&... us) : _value(std::forward<U0>(u0), std::forward<Us>(us)...) {}
private:
T _value;
/* ... */
};
您可以使用创建相应类型的辅助函数:
template <typename T,typename R>
Box<T> make_boxed(const R& value){
return Box<T>(value);
}
必须指定 T
似乎更复杂,另一方面,您可以使用 auto
作为返回类型。完整示例:
#include <string>
template<typename T>
class Box {
public:
Box(const T& value) : _value(value) {};
private:
T _value;
/* ... */
};
typedef Box<std::string> String;
int main(int argc, char* argv[]) {
auto a = make_boxed<std::string>("asd");
}
仅在主要功能部分查看您的源代码:
int main(int argc, char* argv[]) { String a("abc"); std::vector<String> b = { std::string("abc"), std::string("def") }; // error C2664: 'Box<std::string>::Box(const Box<std::string> &)' : // cannot convert argument 1 from 'const char' to 'const std::string &' std::vector<String> c = { "abc", "def" }; }
你的第一行代码:
String a("abc");
正在使用 Box<std::string>
的 typedef
版本,此 class 模板采用 const T&
,因为此版本的模板需要 std::string
它使用 std::string's
构造函数从 const char[3]
构造一个 std::string
,这没问题。
你的下一行代码:
std::vector<String> b = { std::string("abc"), std::string("def") };
是同上的std::vector<T>
。所以这也适用,因为您正在使用有效的 std::string
对象初始化 vector<T>
。
在你的最后一行代码中:
std::vector<String> c = { "abc", "def" };
这里你将 c
声明为 vector<T>
,其中 T
是 Box<std::string>
的 typedef
版本,但是你没有初始化 std::vector<T>
与 Box<std::string>
类型。您正在尝试使用 const char[3]
对象或字符串文字对其进行初始化。
您可以尝试对第三行执行此操作:我没有尝试编译它,但我认为它应该可以工作。
std::vector<String> c = { String("abc"), String("def") };
EDIT -- 我打算使用 String
的构造函数而不是 std::string
进行适当的编辑。