0

I'm learning function objects, and I'm trying this by writing std::transform myself. I created an Increment struct. I will create an object from this struct and use it as a function object in the parameters of my transform function.

This is my Increment struct:

template<typename T>
struct Increment
{
    T by_what;
    void increment(T& item)
    {
        item += by_what;
    }
    void operator() (T& item)
    {
        increment(item);
    }
};

This is my transform free function:

template<typename T>
void transform(std::vector<T>& container, Increment<T> inc)
{
    for(auto& item : container)
        inc(item);
}

But I don't want to make a copy of the inc object and I don't want to change anything about it. That's why I wanted to write const Increment<T>& inc in the parameter but compiler didn't let me.

This is my main function:

int main()
{
    auto v1 = std::vector<int>{10, 20, 30};
    auto inc = Increment<int>{5};
    transform(v1, inc);
}

This is the error:

week5-app2.cpp:50:9: error: no matching function for call to object of type 'const Increment' week5-app2.cpp:73:5: note: in instantiation of function template specialization 'transform' requested here week5-app2.cpp:14:10: note: candidate function not viable: 'this' argument has type 'const Increment', but method is not marked const

Could you explain why writing as const reference is problematic in this case? Thanks in advance for your answers

Piamoon
  • 95
  • 1
  • 7
  • 3
    *"but compiler didn't let me"* - Please include the error message that this generated. Also, how are you calling `transform`? – 0x5453 Nov 20 '20 at 15:39
  • 1
    btw you can change your transform to `template void transform(std::vector& container,const C& c)` to make it more generic. You wont have to change anything else (only the fix from the answer) – 463035818_is_not_an_ai Nov 20 '20 at 15:47

1 Answers1

5

Your compiler does quite a good job at explaining the issue:

candidate function not viable: 'this' argument has type 'const Increment', but method is not marked const

const object can only use const member functions. Change your functions to

template<typename T>
struct Increment
{
    T by_what;
    void increment(T& item) const //const here
    {
        item += by_what;
    }
    void operator() (T& item) const //and here
    {
        increment(item);
    }
};

You should always use const by default to all member function unless they are modifying any data members. This will make keeping const correctness much easier.

Yksisarvinen
  • 18,008
  • 2
  • 24
  • 52