以下代码包含operator()
的const和非const版本。 It outputs
非常数运算符,false
const op,true
const op,true
const op,是的
即如果类型S
的对象是const或提交的指针是const-行// 2
,// 3
,// 4
,则调用const版本。现在,我希望第// 2
行中的代码导致编译时错误,即,我希望const版本只能在const对象上调用。显然,static_assert
上的is_const_v<decltype(*this)>
无法正常工作。还有其他想法吗?
我知道,将非常量变量转换为常量很容易。但这至少会使滥用显而易见。
#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
}
修改
我的问题背后的原因如下。我正在存储提交的指针。这需要丢弃提交的指针的常量性。现在,我想防止const数据被错误地修改。
答案 0 :(得分:7)
您可以明确删除以下版本
void operator()( int const * ) = delete;
禁止
s1( &i2 ); // 2
和
void operator()( int * ) const = delete;
禁止
s2( &i1 ); // 3
答案 1 :(得分:2)
让我们看看如果将this
设为显式参数(虚构语法),它将是非成员函数将如何工作:
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)> >
}
解决方案是删除参数之间具有不同常数的函数:
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;
现在可以使用成员函数完成同样的操作
struct S {
void operator()(int*) {}
void operator()(int const*) const {}
void operator()(int const*) = delete;
void operator()(int*) const = delete;
};
答案 2 :(得分:1)
您可以通过删除带有const int*
的版本来防止调用该函数。例如:
#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)
}