const change without const_cast<> Why no compiler warning/error?

  • A+
Category:Languages

Code sample that demonstrates the problem:

#include <functional> #include <set>  void useCallback(std::function<void(char *)> callback) { }  int main() {     std::function<void(char const *)> callback = [](char const *)     {     };      useCallback(callback);      return 0; } 

Yes, the const removal is benign at the end of the day, useCallback() states in its API that it is prepared to accept and use a callback that modifies its parameter, so it'll do just fine with a function that doesn't.

Why then does the argument that prevents passing a std::set<char *> to a function that expects a std::set<char const *> not apply here? That argument correctly points out that char * and char const * are different types, therefore the two sets are not type equivalent.

Keeping this in mind, why are the types of callback and the parameter to useCallback() not considered different?

-- Edit --

This is using MSVC, VS 2017.

 


That argument correctly points out that char * and char const * are different types, therefore the two sets are not type equivalent.

std::function<void(char *)> and std::function<void(char const *)> are different types too, therefore the two function objects are not type equivalent. It's just that unlike with std::set, they're not required to be type equivalent!

std::function<void(char *)> has a constructor which will accept any object that can be called with a char * argument. std::function<void(char const *)> can be called with a char * argument, so it is fine. It is this same constructor that's used when initialising a std::function<T> from a lambda: there too the types are different, but as long as the lambda can be invoked when passed the argument types in T, it is accepted.

Comment

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: