Dedukcja typu funkcji

0

Cześć,
przykład:

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

using namespace std;
int main(){
    std::vector<int> v_int;
    std::vector<std::string> v_str;

    for(int i = 0;i<5;++i)
        v_int.push_back(i);

    v_str.resize(v_int.size());
    std::transform(v_int.begin(),v_int.end(),v_str.begin(), std::to_string);
}

Błędy kompilatora:

prog.cpp: In function 'int main()':
prog.cpp:15:74: error: no matching function for call to 'transform(std::vector<int>::iterator, std::vector<int>::iterator, std::vector<std::basic_string<char> >::iterator, <unresolved overloaded function type>)'
    std::transform(v_int.begin(),v_int.end(),v_str.begin(), std::to_string);
                                                                          ^
In file included from /usr/include/c++/5/algorithm:62:0,
                 from prog.cpp:3:
/usr/include/c++/5/bits/stl_algo.h:4164:5: note: candidate: template<class _IIter, class _OIter, class _UnaryOperation> _OIter std::transform(_IIter, _IIter, _OIter, _UnaryOperation)
     transform(_InputIterator __first, _InputIterator __last,
     ^
/usr/include/c++/5/bits/stl_algo.h:4164:5: note:   template argument deduction/substitution failed:
prog.cpp:15:74: note:   couldn't deduce template parameter '_UnaryOperation'
    std::transform(v_int.begin(),v_int.end(),v_str.begin(), std::to_string);
                                                                          ^
In file included from /usr/include/c++/5/algorithm:62:0,
                 from prog.cpp:3:
/usr/include/c++/5/bits/stl_algo.h:4201:5: note: candidate: template<class _IIter1, class _IIter2, class _OIter, class _BinaryOperation> _OIter std::transform(_IIter1, _IIter1, _IIter2, _OIter, _BinaryOperation)
     transform(_InputIterator1 __first1, _InputIterator1 __last1,
     ^
/usr/include/c++/5/bits/stl_algo.h:4201:5: note:   template argument deduction/substitution failed:
prog.cpp:15:74: note:   candidate expects 5 arguments, 4 provided
    std::transform(v_int.begin(),v_int.end(),v_str.begin(), std::to_string);
 

Link do ideone: http://ideone.com/M5pXD0

Pytanie: dlaczego kompilator nie potrafi wydedukować, której funkcji to_string użytć?
Skoro w wektorze używany jest int i jes on 'przekazywany' dalej do funkcji szablonowej transform, to dla chyba najlepsze byłoby wywołanie funkcji to_string(int).

2
#include <iostream>
using namespace std;

struct bar {};

void foo(int){}
void foo(char const *){}
void foo(bar){}

template<typename F>
void perf(F f){}

int main() {
	perf(foo); //skąd ma wiedzieć, o które foo Ci chodzi?
	return 0;
}

http://ideone.com/Z60unZ

prog.cpp: In function 'int main()':
prog.cpp10: error: no matching function for call to 'perf(<unresolved overloaded="overloaded" function="function" type="type">)'
perf(foo);
^
prog.cpp6: note: candidate: template<class F> void perf(F)
void perf(F f){}
^
prog.cpp6: note: template argument deduction/substitution failed:
prog.cpp10: note: couldn't deduce template parameter 'F'
perf(foo);

5

Bo skąd miałby?

Szablon std::transform nie jest sparametryzowany względem typu elementu w wektorze (bo nie może być). Parametrami są typy iteratorów oraz typ funktora:

template<typename InputIt, typename OutputIt, typename UnaryOperation>
OutputIt transform(InputIt first1,
                   InputIt last1,
                   OutputIt first2,
                   UnaryOperation unary_op);

Więc jak podasz tam po prostu std::to_string to skąd kompilator miałby wiedzieć którego przeciążenia użyć?

Musisz to pokazać jakoś. Np. za pomocą static_cast albo przypisując wcześniej adres odpowiedniej funkcji do wskaźnika:

std::string (*to_string_int)(int) = &std::to_string;

Niżej @carlosmay pokazał Ci też ładne rozwiązanie z lambdą.

2
std::transform(v_int.begin(), v_int.end(), v_str.begin(), 
        [](auto const& el) { return std::to_string(el); }); 

Jeszcze chciałem dopisać, ale zacytuję:

skąd kompilator miałby wiedzieć którego przeciążenia użyć?

0

Możesz też rzutować na odpowiedni typ, wtedy kompilator będzie wiedział, którego przeciążenia użyć. Ale lambda ładniejsza. :P

1 użytkowników online, w tym zalogowanych: 0, gości: 1