The following code contains a const and a non-const version of operator()
. It outputs
Non-const op, false
Const op, true
Const op, true
Const op, true
I.e. the const version is called if either the object of type S
is const or if the submitted pointer is const - lines // 2
, // 3
, // 4
. Now I want the code in line // 2
to result in a compile time error, i.e. I want the const version to be callable only on const objects. Obviously a static_assert
on is_const_v<decltype(*this)>
will not work. Any other ideas?
I know, it is easy to cast a non-const variable to a const one. But that would make the misuse at least obvious.
#include <iostream>
#include <type_traits>
struct S
{
void
operator()( int * )
{
std::cout << std::boolalpha
<< "Non-const op, "
<< std::is_const_v<typename std::remove_reference_t<decltype(*this)> > << '\n';
}
void
operator()( int const * ) const
{
std::cout << std::boolalpha
<< "Const op, "
<< std::is_const_v<typename std::remove_reference_t<decltype(*this)> > << '\n';
}
};
int main()
{
S s1;
S const s2;
int i1= 0;
int const i2= 1;
s1( &i1 ); // 1
s1( &i2 ); // 2
s2( &i1 ); // 3
s2( &i2 ); // 4
}
Edit
The reasoning behind my question is as follows. I am storing the submitted pointer. This requires casting away constness of the submitted pointer. Now I want to prevent const data being modified erroneously.
You can explicitly delete the following version
void operator()( int const * ) = delete;
to disallow
s1( &i2 ); // 2
and
void operator()( int * ) const = delete;
to disallow
s2( &i1 ); // 3
Let's see how it would work if it would be non member function, if we make this
an explicit parameter (imaginary syntax):
void call(S* this, int*) {
// Wha? we clearly know `S*` is not const
std::is_const_v<typename std::remove_reference_t<decltype(*this)> >
}
void call(S const* this, int const*) {
// same
std::is_const_v<typename std::remove_reference_t<decltype(*this)> >
}
The soluton would be to delete functions with a different constness between parameters:
void call(S* this, int*) {}
void call(S const* this, int const*) {}
void call(S* this, int const*) = delete;
void call(S const* this, int*) = delete;
Now the same can be done with member function:
struct S {
void operator()(int*) {}
void operator()(int const*) const {}
void operator()(int const*) = delete;
void operator()(int*) const = delete;
};
You can prevent the function from being called by deleting the version that takes a const int*
. For example:
#include <iostream>
struct S {
void foo(int*) {
std::cout << "Calling foo(int*)\n";
}
void foo(int const*) const {
std::cout << "Calling foo(int const*)\n";
}
void foo(int const*) = delete;
};
int main() {
S s1;
S const s2;
int i1;
int const i2;
s1.foo(&i1); // This compiles fine (both mutable)
s2.foo(&i2); // This compiles fine too (both const)
s2.foo(&i1); // This also compiles (s2 const, i1 mutable)
s1.foo(&i2); // This fails as intended (s1 mutable, i2 const)
}
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