1

Is it possible to determine if this pointer is a const pointer at compile time? I would like to achieve something like this:

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

Is something like that possible?

Edit

Why do I want to achieve this? I have a class that takes a pointer to a read only table. I would like to have a constructor that would assign this pointer but only if the object will be read only, because editing of the table should be forbidden.

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

If the static_assert was possible the above code would be safe. I could use like this:

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
rozina
  • 4,120
  • 27
  • 49

2 Answers2

4

After you updated your question:

So what you want to have is a constructor that only "returns" a const object.

While there has been a proposal for this feature it never made it into the standard: [N0798]

An easy solution would be to use a concept as described by Mohamad Elghawi.

Another variant might be to get rid of all non-const functions so that the object is per se const even if it's not really.


OLD ANSWER:

Yes, you could use something like this:

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

Still I don't really get how this might be useful as any write access to this or it's members will also fail on compile time if this is const...

Community
  • 1
  • 1
Simon Kraemer
  • 5,700
  • 1
  • 19
  • 49
  • 1
    @AngelusMortis Yes it does. See [here](http://coliru.stacked-crooked.com/a/7da9d9920b689b7f) – Simon Kraemer Mar 02 '16 at 11:57
  • If I make the row method non-const, then I cant access it through a `constexpr Foo` object. – rozina Mar 02 '16 at 11:58
  • The assert is awsome though. I just have to figure out how to implement it in a C++11 compiler with a C++03 standard library. Sucks to work with half ass compilers ;) Thanks for the answer! – rozina Mar 02 '16 at 12:03
  • It seems that the assert does in fact [not work](http://coliru.stacked-crooked.com/a/08eb585295d36ed3) – rozina Mar 02 '16 at 12:08
  • @rozina The assert works in its context.`Foo::Foo()` is not const. You can alter member variables and access this for read and write. – Simon Kraemer Mar 02 '16 at 12:12
  • @rozina The problem is that you want to check whether the variable is const and not whether the actual object is. – Simon Kraemer Mar 02 '16 at 12:16
  • Which variable? I want to know if the object on which the constructor was called is read only or not. – rozina Mar 02 '16 at 12:27
  • @rozina No. You want to know if the variable the object that is created with this operator is assigned to is const or not. `this` in the constructor will never be const. – Simon Kraemer Mar 02 '16 at 12:30
2

No. Not directly. You can try something like this:

#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;
}
Mohamad Elghawi
  • 2,071
  • 10
  • 14
  • You can add `private : Foo() {...}` to really forbid no const instanciation – Garf365 Mar 02 '16 at 11:48
  • @Garf365 Updated. Thanks. – Mohamad Elghawi Mar 02 '16 at 11:50
  • @MohamadElghawi You should delete the copy-constructor. The default one will still allow you something like this: `Foo f(*Foo::Create());` – Simon Kraemer Mar 02 '16 at 12:44
  • @SimonKraemer Thanks. – Mohamad Elghawi Mar 02 '16 at 13:00
  • Is there a way to do this without having to call `new`? – Eric Dec 23 '16 at 19:23
  • @Eric Do you mean by using [std::make_unique](http://en.cppreference.com/w/cpp/memory/unique_ptr/make_unique) or do you mean that you wish to return an object instead of a pointer? – Mohamad Elghawi Dec 26 '16 at 14:50
  • @MohamadElghawi: I mean using something allocated on the stack rather than the heap. Perhaps returning a reference of some kind? – Eric Dec 28 '16 at 19:13
  • @Eric The problem in this case with returning an object by value is that you cannot force the receiver to make it const which is the whole point of this question. You can return a const reference but what would it refer to? You do NOT want to return a reference to a stack based object especially if it is going out of scope. – Mohamad Elghawi Dec 31 '16 at 20:23