为什么隐式转换在 accumulate 中不起作用?
Why does implicit conversion not work in accumulate?
这是 C++ 程序:
#include <iostream>
#include <vector>
#include <numeric>
using namespace std;
int test_string(const string & str) {
return str.size();
}
void main() {
test_string(""); //can compile
vector<string> v;
string sum = accumulate(v.cbegin(), v.cend(), ""); //cannot compile
}
我想在通用 STL 函数 accumulate
的调用中使用从 const char *
到 string
的隐式转换。我知道从 const char *
到字符串的转换不是显式的,因此我们可以将 const char *
参数传递给需要 string
类型的调用。这可以通过上面的test_string
函数来证明。但是当我在 accumulate
中做同样的事情时,编译器抱怨:
error C2440: '=': cannot convert from 'std::basic_string<char,std::char_traits<char>,std::allocator<char>>' to 'const char *'
仅当我将 ""
替换为 string("")
时,该代码才有效。我不明白为什么隐式转换适用于我的自定义函数但不适用于 accumulate
。你能解释一下吗?非常感谢。
PS:我正在使用 Visual Studio 2015.
看看 possible implementation from cppreference
template<class InputIt, class T>
T accumulate(InputIt first, InputIt last, T init)
{
for (; first != last; ++first) {
init = init + *first;
}
return init;
}
当您按照您的方式调用该函数时,InputIt
将被推断为 vector<string>::const_iterator
,而 T
将被推断为 const char*
。正如您在 for 循环中看到的,执行 "accumulation" 的代码行是这样的
init = init + *first
在赋值的右侧,*first
的计算结果为 string&
,init
的计算结果为 const char*
。然后您将使用 std::string::operator+
连接 const char*
和 std::string
实例以返回 std::string
。然后您尝试将 std::string
分配给 const char*
变量。这是不合法的。
这将不起作用,因为 std::string
对象 不能隐式转换或分配 到 const char*
,但反之亦然。
要解决此问题,请将您的代码更改为以下内容(请注意,我用 s
为字符串文字添加了后缀,这是用户定义文字的 C++14 语法(在本例中计算为std::string
) http://en.cppreference.com/w/cpp/string/basic_string/operator%22%22s
int main() {
using namespace std::string_literals;
vector<string> v;
string sum = accumulate(v.cbegin(), v.cend(), ""s);
}
也为, change void main()
to int main()
. For more see What should main() return in C and C++?
std::accumulate 声明为
template< class InputIt, class T >
T accumulate( InputIt first, InputIt last, T init );
这意味着模板参数 T
是从传入的参数推导出来的(即 ""
)。那么它将是const char*
。另一方面,编译器如何执行隐式转换?哪种类型应该是目标类型?
您可以显式传递 std::string
,或显式指定模板参数。例如
// pass a std::string exactly
string sum = accumulate(v.cbegin(), v.cend(), string(""));
// T is specified as std::string explicitly
// "" will be implicitly converted to std::string
string sum = accumulate<decltype(v.cbegin()), string>(v.cbegin(), v.cend(), "");
I don't understand why the implicit conversion works for my custom function but does not work in accumulate. Can you explain that?
甚至没有尝试隐式转换,std::accumulate 只是尝试通过将 std::string
的实例添加到初始化为 auto sum = "";
的总和来进行累加,你会得到与你相同的错误在这种情况下会得到:
std::string s = "abc";
const char* sum = "";
sum = sum + abc; // <-- error
The code works only when I replaced "" with string("")
因为这种方式内部累加器的类型是 std::string
并且一切都按预期工作。你也可以这样做:
string sum = accumulate(v.cbegin(), v.cend(), ""s);
作为旁注,应该是int main() { ... }
,而不是void main
这是 C++ 程序:
#include <iostream>
#include <vector>
#include <numeric>
using namespace std;
int test_string(const string & str) {
return str.size();
}
void main() {
test_string(""); //can compile
vector<string> v;
string sum = accumulate(v.cbegin(), v.cend(), ""); //cannot compile
}
我想在通用 STL 函数 accumulate
的调用中使用从 const char *
到 string
的隐式转换。我知道从 const char *
到字符串的转换不是显式的,因此我们可以将 const char *
参数传递给需要 string
类型的调用。这可以通过上面的test_string
函数来证明。但是当我在 accumulate
中做同样的事情时,编译器抱怨:
error C2440: '=': cannot convert from 'std::basic_string<char,std::char_traits<char>,std::allocator<char>>' to 'const char *'
仅当我将 ""
替换为 string("")
时,该代码才有效。我不明白为什么隐式转换适用于我的自定义函数但不适用于 accumulate
。你能解释一下吗?非常感谢。
PS:我正在使用 Visual Studio 2015.
看看 possible implementation from cppreference
template<class InputIt, class T>
T accumulate(InputIt first, InputIt last, T init)
{
for (; first != last; ++first) {
init = init + *first;
}
return init;
}
当您按照您的方式调用该函数时,InputIt
将被推断为 vector<string>::const_iterator
,而 T
将被推断为 const char*
。正如您在 for 循环中看到的,执行 "accumulation" 的代码行是这样的
init = init + *first
在赋值的右侧,*first
的计算结果为 string&
,init
的计算结果为 const char*
。然后您将使用 std::string::operator+
连接 const char*
和 std::string
实例以返回 std::string
。然后您尝试将 std::string
分配给 const char*
变量。这是不合法的。
这将不起作用,因为 std::string
对象 不能隐式转换或分配 到 const char*
,但反之亦然。
要解决此问题,请将您的代码更改为以下内容(请注意,我用 s
为字符串文字添加了后缀,这是用户定义文字的 C++14 语法(在本例中计算为std::string
) http://en.cppreference.com/w/cpp/string/basic_string/operator%22%22s
int main() {
using namespace std::string_literals;
vector<string> v;
string sum = accumulate(v.cbegin(), v.cend(), ""s);
}
也为void main()
to int main()
. For more see What should main() return in C and C++?
std::accumulate 声明为
template< class InputIt, class T >
T accumulate( InputIt first, InputIt last, T init );
这意味着模板参数 T
是从传入的参数推导出来的(即 ""
)。那么它将是const char*
。另一方面,编译器如何执行隐式转换?哪种类型应该是目标类型?
您可以显式传递 std::string
,或显式指定模板参数。例如
// pass a std::string exactly
string sum = accumulate(v.cbegin(), v.cend(), string(""));
// T is specified as std::string explicitly
// "" will be implicitly converted to std::string
string sum = accumulate<decltype(v.cbegin()), string>(v.cbegin(), v.cend(), "");
I don't understand why the implicit conversion works for my custom function but does not work in accumulate. Can you explain that?
甚至没有尝试隐式转换,std::accumulate 只是尝试通过将 std::string
的实例添加到初始化为 auto sum = "";
的总和来进行累加,你会得到与你相同的错误在这种情况下会得到:
std::string s = "abc";
const char* sum = "";
sum = sum + abc; // <-- error
The code works only when I replaced "" with string("")
因为这种方式内部累加器的类型是 std::string
并且一切都按预期工作。你也可以这样做:
string sum = accumulate(v.cbegin(), v.cend(), ""s);
作为旁注,应该是int main() { ... }
,而不是void main