From: Nick Hounsome on
On 13 June, 11:09, "naikr...(a)gmail.com" <naikr...(a)gmail.com> wrote:
> Is there a safe way to treat Foo<T>* as a Foo<const T>* ?

Are you absolutely sure that you dont want const Foo<T>*?

IMHO It is rarely useful to have Foo<const T> because Foo can always
protect instance of T whether they are const or not - All you acheive
is making the implementation harder. (Foo<const T*> MIGHT make sense).

Compare your class Foo with std::vector - nobody uses vector<const
int> but vector protects its content with overloads like
reference operator[] ( size_type n );
const_reference operator[] ( size_type n ) const;

It is generally logically wrong to be able to change anything OWNED by
a const object hence it is not useful for an object to own const
objects.

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Mathias Gaunard on
On Jun 13, 11:09 am, "naikr...(a)gmail.com" <naikr...(a)gmail.com> wrote:
> Is there a safe way to treat Foo<T>* as a Foo<const T>* ?
>
> Assume that we have freedom to modify template Foo and it has not been
> specialized... but can be specialized if necessary. For sake of
> simplicity lets assume the following simplistic definition of Foo:
>
> template<class T>
> struct Foo {
> T* ptr;
> bool flag;
> ~Foo(){}; // This makes Foo ... not a POD type
>
> };
>

template<class T>
struct Foo {
T* ptr;
bool flag;
~Foo(){};

template<class U>
Foo(const Foo<U>& u) : ptr(u.ptr), flag(u.flag)
{
}
};

This allows to convert Foo<U> to Foo<T> is U is convertible to T.
This is however not exactly what you want.


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Chris Uzdavinis on
On Jun 13, 5:09 am, "naikr...(a)gmail.com" <naikr...(a)gmail.com> wrote:
> Is there a safe way to treat Foo<T>* as a Foo<const T>* ?
>
> Assume that we have freedom to modify template Foo and it has not been
> specialized... but can be specialized if necessary. For sake of
> simplicity lets assume the following simplistic definition of Foo:
>
> template<class T>
> struct Foo {
> T* ptr;
> bool flag;
> ~Foo(){}; // This makes Foo ... not a POD type
>
> };
>
> I know reinterpret_cast would do it. But I am not sure if its the
> safe.

If Foo holds a pointer, and you want to convert Foo<T>* Foo<const T>*, then
you're wanting to work with pointers to pointers? That's hard, as you can't
change the semantics of raw pointers. However, if you treat Foo as a smart
pointer you can use template members to achieve what you're asking, more or
less. (That is, Foo<> is a proxy for the underlying pointer it holds-- in
which case you *can* convert Foo<T> to Foo<const T>, but it is a copy of the
object, not a reinterpreted meaning of the original.

So while this code answers a different question than you asked, it is similar
and may at least help you get an idea of other approaches (in general) to your
problem. (Since, as earlier stated, when you want to do something that is
directly prohibited by the language, you need to question your design.)

template<class T>
struct Foo {
T* ptr;
bool flag;

Foo() : ptr(0), flag(false) { }

template <class U>
Foo(Foo<U> const & rhs) : ptr(rhs.ptr), flag(rhs.flag) { }

template <class U>
operator Foo<U> const () const { return Foo<U>(*this); }

~Foo() { /* do something */ }
};

int main()
{
Foo<int> fi;
Foo<const int> cfi;
cfi = fi; // OK
// fi = cfi; // Error
}


--
Chris

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: pfultz2 on
On Jun 13, 6:09 am, "naikr...(a)gmail.com" <naikr...(a)gmail.com> wrote:
> Is there a safe way to treat Foo<T>* as a Foo<const T>* ?
>
> Assume that we have freedom to modify template Foo and it has not been
> specialized... but can be specialized if necessary. For sake of
> simplicity lets assume the following simplistic definition of Foo:
>
> template<class T>
> struct Foo {
> T* ptr;
> bool flag;
> ~Foo(){}; // This makes Foo ... not a POD type
>
> };
>
> I know reinterpret_cast would do it. But I am not sure if its the
> safe.
>
> -Roshan

{ quoted clc++m banner removed; please do it yourself. -mod }

You could do this by using inheritance, but this requires Foo<const T>
to store the data since this is the base class. You could have it
store a protected mutable data type, but only provide const only
public methods, then in the derived class have the mutable methods.

template<class T>
class Foo : public Foo<const T>
{
public:

//Mutatable methods
//Notice we need to use "this" pointer because the base class is a
templated

T* get()
{
return this->data;
}

//Leave out the set method to avoid the T** -> T const** problem
};

template<class T>
class Foo<const T>
{
protected:
T * data;

public:
//Const methods

const T* get() const
{
return data;
}
};

This is an idea and depends on what you are trying to accomplish.


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Edward Rosten on
On Jun 15, 10:03 am, Nick Hounsome <nick.houns...(a)gmail.com> wrote:
> On 13 June, 11:09, "naikr...(a)gmail.com" <naikr...(a)gmail.com> wrote:

This has been debated here before. Perhaps I have a more coherent
argument this time.

> > Is there a safe way to treat Foo<T>* as a Foo<const T>* ?
>
> Are you absolutely sure that you dont want const Foo<T>*?

Yes...

> IMHO It is rarely useful to have Foo<const T> because Foo can always
> protect instance of T whether they are const or not - All you acheive
> is making the implementation harder. (Foo<const T*> MIGHT make sense).

Unfortunately, you are mistaken. Consider:

template<class C> class Foo
{
private:
C* ptr;
public:
Foo(C* p)
:ptr(p);

C* get(){ return ptr; }
const C* get() const { return ptr; }
};

Now consider you have a function like this:

void func(const Foo<int>& f)
{
Foo<int> not_const_anymore(f);

*not_const_anymore.get() = 0;
}

Because you can copy construct a non-const object from a const one,
you can with some effort circumvent the access controls.

> Compare your class Foo with std::vector - nobody uses vector<const
> int> but vector protects its content with overloads like
> reference operator[] ( size_type n );
> const_reference operator[] ( size_type n ) const;

I agree 100%. When a class has value semantics (e.g. vector<int>) a
const class behaves as if the values it points to are const. That is
nice since a const vector works as a const array. However, if you have
an object with reference semantics, it is impossible so make a const
object behave as if it points to const data properly.

The problem is that const behaves very subtly differently for pointers
than for classes. This is well illustrated by the fact that it is
impossible to get pointer like semantics with classes. Many people
(myself included) understand the precise reasons behind how this
difference manifests, but nevertheless disagree.

The reason is that const A* is just a const version of A*, so the
conversion can happen freely. In this case, the object IS NOT
constant.

However, const A is a version of A, but the object IS constant.


This is a semantic difference. At this point people usually argue that
of course it is the case because the const binds to whatever the *
points to in a declaration. I do not disagree since that is manifestly
the case. However it is still a semantic difference. Auto-consting of
pointers is very different from auto-consting of objects. It is still
impossible to write a class that has pointer like reference semantics.
Because const has a special place in C++ with respect to automatic
conversions, this actually really is a semantic difference.
Conversions to const happen automatically even in the presence of
templates. Other conversions do not. In order to write a class with
pointer like semantics, one needs extra syntactic overhead. Syntactic
overhead is bad.

If you are still unconvinced, let me illustrate it with an example:

Foo is a type which allows slicing. I've omitted the actual slicing
part. Assume it happens.

template<class C> struct Foo
{
const Foo<C> nonconst_slice()
{
return Foo();
}

const Foo<const C> const_slice()
{
return Foo<const C>();
}

};

template<class C> struct Foo<const C>
{
Foo();
Foo(const Foo<C>&); //Allow automatic conversion to Foo<const C>;
};



void do_something_int(const Foo<const int>& f);

template<class C> void do_something(const Foo<const C>& f);

int main()
{
Foo<int> f;

do_something_int(f);
do_something_int(f.nonconst_slice());
do_something_int(f.const_slice());

do_something(f); //Error: no automatic conversion. Syntactic overhead
required
do_something(f.nonconst_slice()); //Error: no automatic conversion:
Syntactic overhead required
do_something(f.const_slice());
}

See? Classes with pointer/reference semantics simply do not behave as
nicely as pointers.

> It is generally logically wrong to be able to change anything OWNED by
> a const object hence it is not useful for an object to own const
> objects.

I largely agree. C++ makes the unusual case the default and the
obvious case impossible to implement.

-Ed
--
(You can't go wrong with psycho-rats.)(http://mi.eng.cam.ac.uk/~er258)

/d{def}def/f{/Times s selectfont}d/s{11}d/r{roll}d f 2/m{moveto}d -1
r 230 350 m 0 1 179{ 1 index show 88 rotate 4 mul 0 rmoveto}for/s 12
d f pop 235 420 translate 0 0 moveto 1 2 scale show showpage




--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]