为什么我的 class 的复制初始化不适用于使用字符串文字的 string_view?
Why does copy initialization of my class not work with string_view using string literals?
我有以下代码:
#include <string_view>
class Foo
{
public:
Foo(std::string_view) {}
};
当我这样做时,一切都编译正常(使用 clang v8,C++17):
Foo f("testing");
但是,如果我使用复制初始化,它会失败:
Foo f = "testing";
诊断:
prog.cc:15:9: error: no viable conversion from 'const char [8]' to 'Foo'
Foo f = "testing";
^ ~~~~~~~~~
prog.cc:7:7: note: candidate constructor (the implicit copy constructor) not viable: no known conversion from 'const char [8]' to 'const Foo &' for 1st argument
class Foo
^
prog.cc:7:7: note: candidate constructor (the implicit move constructor) not viable: no known conversion from 'const char [8]' to 'Foo &&' for 1st argument
class Foo
^
prog.cc:10:5: note: candidate constructor not viable: no known conversion from 'const char [8]' to 'std::string_view' (aka 'basic_string_view<char>') for 1st argument
Foo(std::string_view) {}
^
1 error generated.
查看 constructors for string_view,我没有看到任何占用 char const[]
的重载,这可能是问题所在吗?我意识到我可以使用 "testing"sv
来解决这个问题,但我觉得字符串文字大小写也应该有效。
为什么复制初始化案例不起作用?我怎样才能让它与字符串文字一起工作?
Foo f = "testing";
是 copy initialization,它要求从 "testing"
(属于 const char[8]
类型)到 Foo
的隐式转换。 "testing"
可能衰减到 const char*
,然后仍然需要两个用户定义的转换。从 const char*
到 std::string_view
的转换,以及从 std::string_view
到 Foo
的转换。但是在一个隐式转换序列中只允许一个用户自定义转换。
Foo f("testing");
是 direct initialization,其行为不同。 "testing"
衰减为const char*
,然后转换为std::string_view
,作为Foo
的构造函数的参数直接初始化f
。
In addition, the implicit conversion in copy-initialization must produce T directly from the initializer, while, e.g. direct-initialization expects an implicit conversion from the initializer to an argument of T's constructor.
Implicit conversion is defined in terms of copy-initialization: if an object of type T can be copy-initialized with expression E, then E is implicitly convertible to T.
作为解决方法,如果您想坚持复制初始化,可以减少所需的用户定义转换。正如您所展示的,应用 Foo f = "testing"sv;
或 Foo f = std::string_view("testing");
是个好主意,它们具有相同的效果。
我有以下代码:
#include <string_view>
class Foo
{
public:
Foo(std::string_view) {}
};
当我这样做时,一切都编译正常(使用 clang v8,C++17):
Foo f("testing");
但是,如果我使用复制初始化,它会失败:
Foo f = "testing";
诊断:
prog.cc:15:9: error: no viable conversion from 'const char [8]' to 'Foo'
Foo f = "testing";
^ ~~~~~~~~~
prog.cc:7:7: note: candidate constructor (the implicit copy constructor) not viable: no known conversion from 'const char [8]' to 'const Foo &' for 1st argument
class Foo
^
prog.cc:7:7: note: candidate constructor (the implicit move constructor) not viable: no known conversion from 'const char [8]' to 'Foo &&' for 1st argument
class Foo
^
prog.cc:10:5: note: candidate constructor not viable: no known conversion from 'const char [8]' to 'std::string_view' (aka 'basic_string_view<char>') for 1st argument
Foo(std::string_view) {}
^
1 error generated.
查看 constructors for string_view,我没有看到任何占用 char const[]
的重载,这可能是问题所在吗?我意识到我可以使用 "testing"sv
来解决这个问题,但我觉得字符串文字大小写也应该有效。
为什么复制初始化案例不起作用?我怎样才能让它与字符串文字一起工作?
Foo f = "testing";
是 copy initialization,它要求从 "testing"
(属于 const char[8]
类型)到 Foo
的隐式转换。 "testing"
可能衰减到 const char*
,然后仍然需要两个用户定义的转换。从 const char*
到 std::string_view
的转换,以及从 std::string_view
到 Foo
的转换。但是在一个隐式转换序列中只允许一个用户自定义转换。
Foo f("testing");
是 direct initialization,其行为不同。 "testing"
衰减为const char*
,然后转换为std::string_view
,作为Foo
的构造函数的参数直接初始化f
。
In addition, the implicit conversion in copy-initialization must produce T directly from the initializer, while, e.g. direct-initialization expects an implicit conversion from the initializer to an argument of T's constructor.
Implicit conversion is defined in terms of copy-initialization: if an object of type T can be copy-initialized with expression E, then E is implicitly convertible to T.
作为解决方法,如果您想坚持复制初始化,可以减少所需的用户定义转换。正如您所展示的,应用 Foo f = "testing"sv;
或 Foo f = std::string_view("testing");
是个好主意,它们具有相同的效果。