在编译时确定这是否是只读的
Determine at compile time if this is read only
是否可以在编译时判断this
指针是否为const指针?
我想实现这样的目标:
class Foo
{
Foo()
{
static_assert( is this read only?, "works only on read only objects");
}
}
这样的事情可能吗?
编辑
我为什么要实现这个目标?我有一个 class,它接受一个指向只读 table 的指针。我想要一个构造函数来分配这个指针,但前提是该对象是只读的,因为应该禁止编辑 table。
class Foo
{
public:
template <std::size_t N>
explicit constexpr Foo(const int(&table)[N])
: m_table(table),
m_size(N)
{
}
Foo(const Foo& rhs)
: m_table(new int[rhs.size()]),
m_size(rhs.size())
{
// copy rhs.m_table into m_table
}
std::size_t size() const { return m_size; }
const int& row(std::size_t i) const { assert(m_size > i); return m_table[i]; }
int& row(std::size_t i) { assert(m_size > i); return m_table[i]; }
private:
int* m_table = nullptr;
std::size_t m_size = 0;
};
如果 static_assert 可行,上述代码将是安全的。我可以这样使用:
constexpr int table[10];
constexpr Foo foo(table); // ok not an error
auto& a = foo.row(0); // error
const auto& b = foo.row(0) // ok
Foo bar(foo);
auto& b = bar.row(0); // ok
Foo foobar(table) // static_assert if possible
没有。不直接。你可以尝试这样的事情:
#include <memory>
class Foo
{
Foo() = default;
Foo(const Foo&) = delete;
public:
static const Foo* Create()
{
return new Foo();
}
};
int main()
{
std::unique_ptr<const Foo> f(Foo::Create());
//std::unique_ptr<Foo> f(Foo::Create()); // ERROR
return 0;
}
更新问题后:
所以你想要的是一个只有 "returns" const 对象的构造函数。
虽然有针对此功能的提案,但它从未成为标准:[N0798]
一个简单的解决方案是使用 描述的概念。
另一种变体可能是去掉所有 non-const
函数,这样对象本身就是 const
,即使它不是真的。
旧答案:
是的,你可以使用这样的东西:
class Foo
{
public:
Foo()
{
}
void doSomething()
{
static_assert(std::is_const<std::remove_pointer_t<decltype(this)>>::value, "works only on read only objects");
}
void doSomethingConst() const
{
static_assert(std::is_const<std::remove_pointer_t<decltype(this)>>::value, "works only on read only objects");
}
};
我仍然不明白这有什么用,因为如果这是 const,对它或它的成员的任何写访问也会在编译时失败...
是否可以在编译时判断this
指针是否为const指针?
我想实现这样的目标:
class Foo
{
Foo()
{
static_assert( is this read only?, "works only on read only objects");
}
}
这样的事情可能吗?
编辑
我为什么要实现这个目标?我有一个 class,它接受一个指向只读 table 的指针。我想要一个构造函数来分配这个指针,但前提是该对象是只读的,因为应该禁止编辑 table。
class Foo
{
public:
template <std::size_t N>
explicit constexpr Foo(const int(&table)[N])
: m_table(table),
m_size(N)
{
}
Foo(const Foo& rhs)
: m_table(new int[rhs.size()]),
m_size(rhs.size())
{
// copy rhs.m_table into m_table
}
std::size_t size() const { return m_size; }
const int& row(std::size_t i) const { assert(m_size > i); return m_table[i]; }
int& row(std::size_t i) { assert(m_size > i); return m_table[i]; }
private:
int* m_table = nullptr;
std::size_t m_size = 0;
};
如果 static_assert 可行,上述代码将是安全的。我可以这样使用:
constexpr int table[10];
constexpr Foo foo(table); // ok not an error
auto& a = foo.row(0); // error
const auto& b = foo.row(0) // ok
Foo bar(foo);
auto& b = bar.row(0); // ok
Foo foobar(table) // static_assert if possible
没有。不直接。你可以尝试这样的事情:
#include <memory>
class Foo
{
Foo() = default;
Foo(const Foo&) = delete;
public:
static const Foo* Create()
{
return new Foo();
}
};
int main()
{
std::unique_ptr<const Foo> f(Foo::Create());
//std::unique_ptr<Foo> f(Foo::Create()); // ERROR
return 0;
}
更新问题后:
所以你想要的是一个只有 "returns" const 对象的构造函数。
虽然有针对此功能的提案,但它从未成为标准:[N0798]
一个简单的解决方案是使用
另一种变体可能是去掉所有 non-const
函数,这样对象本身就是 const
,即使它不是真的。
旧答案:
是的,你可以使用这样的东西:
class Foo
{
public:
Foo()
{
}
void doSomething()
{
static_assert(std::is_const<std::remove_pointer_t<decltype(this)>>::value, "works only on read only objects");
}
void doSomethingConst() const
{
static_assert(std::is_const<std::remove_pointer_t<decltype(this)>>::value, "works only on read only objects");
}
};
我仍然不明白这有什么用,因为如果这是 const,对它或它的成员的任何写访问也会在编译时失败...