模板中的隐式const转换

kee*_*ety 0 c++ const-cast

我遇到类似于下面的代码片段,它会抛出编译器错误,因为它使用了一个const_iterator.是有一个原因vec.end()std::copy不会隐获得const投?

int main(int argc, char* argv[]) {

    vector<int> vec;
    vec.push_back(20);
    vec.push_back(30);
    vector<int> copy_vec;
    vector<int>::const_iterator i = vec.begin();
    std::copy(i,vec.end(),back_inserter(copy_vec));
    cerr<<copy_vec.size()<<endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

Naw*_*waz 5

不需要std::copy,也不需要一对迭代器.

这样做:

vector<int> copy_vec(vec); //use the copy constructor!
Run Code Online (Sandbox Code Playgroud)

而且你已经完成了!

至于你的代码为什么它会给出错误,因为第一个迭代器std::copy是a const_iterator,但第二个迭代器只是iterator.两者都必须是相同的类型,但它们不是,因此模板参数推导失败,因为std::copy它是一个函数模板.

要通过示例来理解这一点,请考虑以下简单代码:

template<typename T>
void f(T a, T b) {}

int main()
{
    int a = 100;
    char b = 'A';
    f(a,b);
}
Run Code Online (Sandbox Code Playgroud)

这是错误的(见ideone):

prog.cpp:8: error: no matching function for call to ‘f(int&, char&)’
Run Code Online (Sandbox Code Playgroud)

它不会编译,因为我们依赖于模板参数推导.由于第一个参数和第二个参数的类型是完全相同的函数模板相同,但我们调用这个函数传递a(这是int)作为第一个参数,b(这是char)作为第二个参数,它不能推断出T唯一不同类型的参数!请注意,在模板参数扣除期间不考虑转换.

但是,如果我们不依赖于模板参数推导,而是明确地提供模板参数,那么它将起作用(参见ideone):

f<int>(a,b);  //works!
Run Code Online (Sandbox Code Playgroud)

它的工作原理是不需要T从函数参数中推断出来!

同样,如果您提供模板参数std::copy,那么即使您的代码也可以工作(请参阅ideone):

std::copy<vector<int>::const_iterator>(i,vec.end(),back_inserter(copy_vec));
       //^^^^^^^^^^^^^^^^^^^^^^^^^^^^ explicitly provide template argument!
Run Code Online (Sandbox Code Playgroud)

它的工作原理是因为iterator可以转换成const_iterator,但const_iterator不能转换成iterator哪个意味着以下会产生错误(参见ideone):

std::copy<vector<int>::iterator>(i,vec.end(),back_inserter(copy_vec));
        //^^^^^^^^^^^^^^^^^^^^^ non-const iterator!
Run Code Online (Sandbox Code Playgroud)