传递std算法。模板演绎

时间:2017-01-31 09:25:28

标签: c++ templates functor template-deduction

我试图让这个小例子起作用

#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    std::vector<char> v{'a', 'b', 'c', 'd'};
    std::transform(v.begin(), v.end(), v.begin(), std::toupper);
    std::for_each(v.begin(), v.end(), [](char & c) {
                    std::cout << c << " ";
                  });
}

我认为很明显,我想要实现的目标。但是,我收到了这些错误

    ||=== Build file: "no target" in "no project" (compiler: unknown) ===|
C:\Users\vitaly.bushaev\Documents\vk cup\1.cpp||In function 'int main()':|
C:\Users\vitaly.bushaev\Documents\vk cup\1.cpp|8|error: no matching function for call to 'transform(std::vector<char>::iterator, std::vector<char>::iterator, std::vector<char>::iterator, <unresolved overloaded function type>)'|
C:\Users\vitaly.bushaev\Documents\vk cup\1.cpp|8|note: candidates are:|
C:\Program Files (x86)\CodeBlocks\MinGW\lib\gcc\mingw32\4.9.2\include\c++\bits\stl_algo.h|4152|note: template<class _IIter, class _OIter, class _UnaryOperation> _OIter std::transform(_IIter, _IIter, _OIter, _UnaryOperation)|
C:\Program Files (x86)\CodeBlocks\MinGW\lib\gcc\mingw32\4.9.2\include\c++\bits\stl_algo.h|4152|note:   template argument deduction/substitution failed:|
C:\Users\vitaly.bushaev\Documents\vk cup\1.cpp|8|note:   couldn't deduce template parameter '_UnaryOperation'|
C:\Program Files (x86)\CodeBlocks\MinGW\lib\gcc\mingw32\4.9.2\include\c++\bits\stl_algo.h|4189|note: template<class _IIter1, class _IIter2, class _OIter, class _BinaryOperation> _OIter std::transform(_IIter1, _IIter1, _IIter2, _OIter, _BinaryOperation)|
C:\Program Files (x86)\CodeBlocks\MinGW\lib\gcc\mingw32\4.9.2\include\c++\bits\stl_algo.h|4189|note:   template argument deduction/substitution failed:|
C:\Users\vitaly.bushaev\Documents\vk cup\1.cpp|8|note:   candidate expects 5 arguments, 4 provided|
||=== Build failed: 1 error(s), 0 warning(s) (0 minute(s), 0 second(s)) ===|

所以我读这篇文章并理解错误,但我无法理解为什么会这样。当然这很好用:

#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    std::vector<char> v{'a', 'b', 'c', 'd'};
    using it = std::vector<char>::iterator;
    std::transform<it, it, int (int)>(v.begin(), v.end(), v.begin(), std::toupper);
    std::for_each(v.begin(), v.end(), [](char & c) {
                    std::cout << c << " ";
                  });
}

所以这就是问题所在:

1)为什么c ++不能在这里推导出模板参数?

2)有没有解决方法,不指定类型?

1 个答案:

答案 0 :(得分:3)

std::toupper有多个重载。

模板推导在重载选择之前发生,因此您必须具体或将调用包装在lambda或函数对象中。

#include <iostream>
#include <vector>
#include <algorithm>



int main() {
    std::vector<char> v{'a', 'b', 'c', 'd'};

    // method 1
    struct make_upper
    {
        int operator()(int ch) const { return std::toupper(ch); }
    };
    std::transform(v.begin(), v.end(), v.begin(), make_upper());

    // method 2
    std::transform(v.begin(), v.end(), v.begin(), [](auto&& ch) { return std::toupper(ch); });
}

参考:

http://en.cppreference.com/w/cpp/locale/toupper http://en.cppreference.com/w/cpp/string/byte/toupper