3

I tried to implement a map operator based on the C++ operator ->*. The purpose of this operator was to elegantly map/transform zero terminated char* strings and wchar_t* strings inplace.

template<typename T>
T* operator->*(T* iteratee, std::function<T(T)> mapFun)  {
    for(T* it = iteratee; *it; ++it)
      *it = mapFun(*it);
    return iteratee;
}

using namespace std;

int main()
{
   char msg[] = "Hello World!";

   cout << msg << endl;
   cout << msg->*([](char c ) { return c+1; }) << endl;   
}

Desired output is:

Hello World!
Ifmmp!Xpsme"

But instead I only get the following error:

21:15: error: no match for 'operator->*' (operand types are 'char*' and 'main()::<lambda(char)>')
21:15: note: candidate is:
10:4: note: template<class T> T* operator->*(T*, std::function<T(T)>)
10:4: note:   template argument deduction/substitution failed:
21:46: note:   'main()::<lambda(char)>' is not derived from 'std::function<T(T)>'

Why is this happening?


I know, I can fix the Problem by either calling the operator explicitly, which makes the operator pretty inconvenient

cout << operator->*<char>(msg, [](char c ) { return c+1; }) << endl;

or by adding a second template argument to the operator:

template<typename T, typename F>
T* operator->*(T* iteratee, F mapFun)  {
for(T* it = iteratee; *it; ++it)
      *it = mapFun(*it);
    return iteratee;
}

But this it not optimal, because the compiler doesn't complain, when I pass a function of the wrong type like the following usage, which compiles without warning:

cout << msg->*([](int i) { return 'a'+i; }) << endl;

So, how can I use the std::function-version of the operator without explicitly mentioning the template arguments?

whY
  • 189
  • 1
  • 10
  • Well, I wrote a lengthy answer explaining it from the basics, but by that time, the topic is closed, and I could post it here. But since the duplicate topic is almost same, I posted [my answer in the other topic](http://stackoverflow.com/a/31119355/415784). – Nawaz Jun 29 '15 at 15:18

0 Answers0