为什么隐式转换在累积中不起作用?

use*_*911 12 c++ string templates implicit-conversion

这是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
}
Run Code Online (Sandbox Code Playgroud)

我想使用隐式转换,从const char *string仿制STL函数的调用accumulate.我知道转换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 *'
Run Code Online (Sandbox Code Playgroud)

代码工作只有当我更换""使用string("").我不明白为什么隐式转换适用于我的自定义函数但不起作用accumulate.你能解释一下吗?非常感谢.

PS:我正在使用Visual Studio 2015.

son*_*yao 12

std :: accumulate声明为

template< class InputIt, class T >
T accumulate( InputIt first, InputIt last, T init );
Run Code Online (Sandbox Code Playgroud)

这意味着模板参数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(), "");
Run Code Online (Sandbox Code Playgroud)

  • 在`C++ 11及更高版本中,`string("")`也可以用``"s`代替 (2认同)
  • @Curious:C++ 14:http://en.cppreference.com/w/cpp/string/basic_string/operator%22%22s (2认同)

Cur*_*ous 11

看一下cppreference可能的实现

template<class InputIt, class T>
T accumulate(InputIt first, InputIt last, T init)
{
    for (; first != last; ++first) {
        init = init + *first;
    }
    return init;
}
Run Code Online (Sandbox Code Playgroud)

当你以你的方式调用函数时,InputIt将被推断为a vector<string>::const_iterator并且T将被推断为a const char*.正如你在for循环中看到的那样,执行"累积"的代码行就是这个

init = init + *first
Run Code Online (Sandbox Code Playgroud)

这里的赋值的右手边*first将评估的string&init将评估的const char*.然后你将使用std::string::operator+它将连接const char*std::string实例来std::string回来.然后你试图分配std::string一个const char*变量.这不合法.

这将无法正常工作,std::string对象是不隐式转换或分配const char*,情况正好相反.然而.

要解决此问题,请将您的代码更改为以下内容(请注意,我将字符串文字后缀为a s,这是用户定义文字的C++ 14语法(在本例中计算结果为a std::string)http://en.cppreference.com/W/CPP /串/ basic_string的/操作员%22%22S

int main() {
    using namespace std::string_literals;
    vector<string> v;
    string sum = accumulate(v.cbegin(), v.cend(), ""s); 
}
Run Code Online (Sandbox Code Playgroud)

同样如评论中所述,void main()改为int main().有关更多信息,请参阅C和C++中main()返回的内容?