I want to create a templated function that works the same way for const and non-const data, except that it returns a const or non-const pointer as appropriate.
For instance, I want to return a pointer to a matching element in a container:
template <class Container, class Pred>
typename Container::value_type* getValuePtrIf(Container& c, Pred pred)
{
auto it=std::find_if(c.begin(), c.end(), pred);
return (it!=c.end()) ? &(*it) : nullptr;
}
However I can't get this to build for const and non-const calls. If I omit the const from the Container& c
declaration then it can't return a const pointer, but if I change to const Container& c
then I can return a const pointer, but then the non-const case doesn't build.
Is there a way of defining this so that the const
is interpreted as being part of the Container
template parameter so that I only have to define one version of this function?
There are legitimate uses of having two member functions with the same name with one const and the other not, such as the begin and end iterator functions, which return non-const iterators on non-const objects, and const iterators on const objects, but if it's casting from const to do something, it smells like fish.
const member functions may be invoked for const and non-const objects. non-const member functions can only be invoked for non-const objects. If a non-const member function is invoked on a const object, it is a compiler error.
The statement int* c = const_cast<int>(b) returns a pointer c that refers to a without the const qualification of a . This process of using const_cast to remove the const qualification of an object is called casting away constness. Consequently the compiler does allow the function call f(c) .
From the code it seems you have C++11 support in your compiler. Then you can probably use decltype
and trailing return types as well:
template <class Container, class Pred>
auto getValuePtrIf(Container& c, Pred pred) -> decltype(&*std::begin(c))
{
auto it=std::find_if(std::begin(c), std::end(c), pred);
return (it!=std::end(c)) ? &(*it) : nullptr;
}
it
will be of whatever type std::begin(c)
gives you (iterator
or const_iterator
), so the type of &(*it)
is the same as of decltype(&*std::begin(c))
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With