如果只读,则在编译时确定

时间:2016-03-02 11:36:03

标签: c++ c++11 readonly static-assert

是否有可能在编译时确定this指针是否为const指针? 我想实现这样的目标:

class Foo
{
    Foo() 
    { 
        static_assert( is this read only?, "works only on read only objects"); 
    }
}

这样的事情可能吗?

修改

为什么我要实现这个目标?我有一个类,它指向一个只读表。我想有一个构造函数来分配这个指针,但只有当对象只读时才会被读取,因为应该禁止编辑表。

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

2 个答案:

答案 0 :(得分:4)

更新问题后:

所以你想拥有的只是一个“返回”const对象的构造函数。

虽然有针对此功能的提案,但它从未进入标准:[N0798]

一个简单的解决方案是使用Mohamad Elghawi所描述的概念。

另一种变体可能是摆脱所有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");
    }

};

DEMO

我仍然不知道这可能有用,因为如果这是const,任何对此或它的成员的写访问也将在编译时失败...

答案 1 :(得分:2)

没有。不是直接的。你可以尝试这样的事情:

#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;
}