Topic: const_cast prohibitted on pointers to member function


Author: "John Lund" <jlund@allaire.com>
Date: 1999/09/14
Raw View
>I don't think this would work because the original poster wanted to store
>either a pointer to a non-const function or a pointer to a const function,
>with the choice determined at run time.  If the choice were determined at
>compile time, then yes, a template would be better.  Or am I missing
>something?


I've experimented with both a version that parameterizes the function
pointer and a version that (sort-of) hides the function pointer via a union.
The former is flexible, but not especially nice to use (i.e., it leads to a
lot of typedefs in code that uses it). The latter has a runtime cost, so it
led me to wondering if I couldn't cast away const from the function pointer
deep in the bowels of the implementation. I knew reinterpret_cast wouldn't
work on most platforms I use.

I recognize that this const_cast would be eyebrow-raising, but I've been
curious why it was left undefined by the standard. After all, it wouldn't be
undefined if the standard defined behavior for it, and it's the rationale
behind leaving it undefined that I was looking for.

I can't say I understand why, but I'm moving on. Thanks to everyone who took
the time to respond.

-john, jlund@allaire.com




[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Valentin Bonnard <Bonnard.V@wanadoo.fr>
Date: 1999/09/11
Raw View
Siemel B. Naran wrote:

> How about a union?

How about a template ?

--

Valentin Bonnard


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 1999/09/12
Raw View
In article <37D92EDF.3AD5@wanadoo.fr>, Valentin Bonnard
<Bonnard.V@wanadoo.fr> writes
>ANY use (except perhaps casting it back to its original
>type) of the value of (void(*)(const int*))p, p being
>of type void(*)(int*), causes UNDEFINED BEHAVIOUR.

However any implementation can always define that behaviour and remain
fully conforming.  In that case the programmer would know what the non-
portable behaviour was.


Francis Glassborow      Journal Editor, Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: sbnaran@uiuc.edu (Siemel B. Naran)
Date: 1999/09/13
Raw View
On 11 Sep 1999 17:17:39 GMT, Valentin Bonnard <Bonnard.V@wanadoo.fr> wrote:
>Siemel B. Naran wrote:

>> How about a union?
>
>How about a template ?

I don't think this would work because the original poster wanted to store
either a pointer to a non-const function or a pointer to a const function,
with the choice determined at run time.  If the choice were determined at
compile time, then yes, a template would be better.  Or am I missing
something?

--
--------------
siemel b naran
--------------
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: Jim Hyslop <jim.hyslop@leitch.com>
Date: 1999/09/09
Raw View
In article <rt0ef52oj7137@corp.supernews.com>,
  "Michael VanLoon" <michaelv@edifecs.com> wrote:
> John Lund <jlund@allaire.com> wrote in message
> news:rsu4ju19j7132@corp.supernews.com...
> > What are the reasons for prohibiting const_cast on pointers to
member
> > functions?
> > Don't the reasons for using const_cast on other types also apply to
> function
> > pointers (e.g., to use an incorrectly-specified interface in a
> third-party
> > library)?
> >
> > typedef void (MyClass::*TNonConstMemFun)();
> > TNonConstMemFun pFun =
> >     const_cast<TNonConstMemFun>(&MyClass::MyConstMemFun);
>
> What if every declared instance of this class was const, and the
> compiler decided to stick this class instance in read-only memory?
Would that be so bad, though?

Consider this:
class T
{
public:
   void constFunc() const
    { /* Can't do anything to modify the object... */ }
   void nonConstFunc();
};

typedef void (T::*TNonConstMemFun)();

const T t;

int main()
{
   // The following line won't actually compile... (at least,
   // it shouldn't ;-)
   TNonConstMemFun mf = const_cast<TNonConstMemFun>(&T::constFunc);
   (t.*mf)(); // This is exactly the same as:
   t.constFunc();
   return 0;
}

Since T::constFunc cannot modify the object, it is still safe to call
constFunc on it, even through a pointer-to-member that thinks it's a
non-const function.

Interestingly, MSVC allows this:
// using class, typedefs and 't' from above:
int main()
{
   TNonConstMemFun mf = &T::nonConstFunc;
   (t.*mf)(); // Oops - calling a non-const function on a const object!!
}

If I read section 5.2.5/4 correctly (and I sure hope I have!), my second
version of main is ill-formed.

--
Jim
I ignore all email from recruitment agencies.
Please do not send me email with questions - post
here.


Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: Valentin Bonnard <Bonnard.V@wanadoo.fr>
Date: 1999/09/09
Raw View
John Lund wrote:

> What are the reasons for prohibiting const_cast on pointers to member
> functions?

Because you could _never_ use the resulting pointer
w/o causing undefined behaviour. use reinterpret_cast
if you know whay you are doing and that this particular
undefined behaviour works with your compiler.

Of course, this use of reinterpret_cast makes your
program unportable.

This is explained in the ARM, in CD2 (5.2.11/12),
and in the standard (5.2.11/12).

--

Valentin Bonnard
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: "John Lund" <jlund@allaire.com>
Date: 1999/09/10
Raw View
I understand why the behavior is undefined if the function actually changed
the state of the object (a cast like that would be evil), but what if you
*knew* it didn't? Isn't casting-away constness on data that is modified also
undefined?

Consider this:
I've used a couple older libraries that were incorrectly defined for
non-const parameters like char* (i.e., the documentation guaranteed that the
data would remain unmodified, but the interface lacked a const specification
on the parameter). I haven't ever run into a library that took a non-const
function pointer when it should've taken a const one, but shouldn't that
also be a fair use for const_cast?

Also, suppose you had a class something like this:

template<typename T>
class dtor_fun
{
public:
    typedef void (T::*fun_type)();
    typedef void (T::*const_fun_type)() const;

    dtor_fun(T* pObj, fun_type pMemFun);
    dtor_fun(const T* pObj, const_fun_type pMemFun);

    // Invokes pMemFun.
    ~dtor_fun();

    // details omitted
};

Suppose the pointers (both pObj and pMemFun) are never exposed. The ctors
control const-ness, so if you could employ a couple casts in the second ctor
you'd be able to store the function pointer in the same space without any
runtime cost.

I confess that both examples I've offered seem extremely special-case. Maybe
they are not just prohibited, but illegitimate cases?

-john, jlund@allaire.com
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: Valentin Bonnard <Bonnard.V@wanadoo.fr>
Date: 1999/09/11
Raw View
> I understand why the behavior is undefined if the
> function actually changed the state of the object
> (a cast like that would be evil), but what if you
> *knew* it didn't?

I fear that I haven't been clear enough, so let me repeat:

Because you could NEVER use the resulting pointer
w/o causing undefined behaviour.

The resulting pointer can be for ex. the result of
(void(*)(const int*))p with p of type void(*)(int*).

or

ANY use (except perhaps casting it back to its original
type) of the value of (void(*)(const int*))p, p being
of type void(*)(int*), causes UNDEFINED BEHAVIOUR.

Any use means any use via the function call operator "()".
There is no 'what if' part.

(Again, you may still do the cast if you really know
what you are doing.)

--

Valentin Bonnard
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: sbnaran@uiuc.edu (Siemel B. Naran)
Date: 1999/09/11
Raw View
On 10 Sep 99 03:29:14 GMT, John Lund <jlund@allaire.com> wrote:

>class dtor_fun
>{
>public:
>    typedef void (T::*fun_type)();
>    typedef void (T::*const_fun_type)() const;
>
>    dtor_fun(T* pObj, fun_type pMemFun);
>    dtor_fun(const T* pObj, const_fun_type pMemFun);
>
>    // Invokes pMemFun.
>    ~dtor_fun();
>
>    // details omitted
>};

How about a union?

class dtor_fun
{
   public:
      dtor_fun(T       * pObj, void (T::*fun)()      );
      dtor_fun(T const * pObj, void (T::*fun)() const);
      ~dtor();

   private:
      enum { plain, const } Which;
      union
      {
         void (T::*plain)()      ;
         void (T::*const)() const;
      } pMemFun;
      union
      {
         T       * plain;
         T const * const;
      } pObj;
};

--
--------------
siemel b naran
--------------


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: "John Lund" <jlund@allaire.com>
Date: 1999/09/09
Raw View
What are the reasons for prohibiting const_cast on pointers to member
functions?
Don't the reasons for using const_cast on other types also apply to function
pointers (e.g., to use an incorrectly-specified interface in a third-party
library)?

typedef void (MyClass::*TNonConstMemFun)();
TNonConstMemFun pFun =
    const_cast<TNonConstMemFun>(&MyClass::MyConstMemFun);

-john, jlund@allaire.com
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: "Michael VanLoon" <michaelv@edifecs.com>
Date: 1999/09/06
Raw View
John Lund <jlund@allaire.com> wrote in message
news:rsu4ju19j7132@corp.supernews.com...
> What are the reasons for prohibiting const_cast on pointers to member
> functions?
> Don't the reasons for using const_cast on other types also apply to
function
> pointers (e.g., to use an incorrectly-specified interface in a
third-party
> library)?
>
> typedef void (MyClass::*TNonConstMemFun)();
> TNonConstMemFun pFun =
>     const_cast<TNonConstMemFun>(&MyClass::MyConstMemFun);

What if every declared instance of this class was const, and the
compiler decided to stick this class instance in read-only memory?
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: "John Lund" <jlund@allaire.com>
Date: 1999/09/03
Raw View
What are the reasons for prohibiting const_cast on pointers to member
functions?
Don't the reasons for using const_cast on other types also apply to function
pointers (e.g., to use an incorrectly-specified interface in a third-party
library)?

typedef void (MyClass::*TNonConstMemFun)();
TNonConstMemFun pFun =
    const_cast<TNonConstMemFun>(&MyClass::MyConstMemFun);

-john, jlund@allaire.com
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: "Gene Bushuyev" <gbush@my-deja.com>
Date: 1999/09/03
Raw View
John Lund <jlund@allaire.com> wrote in message
news:rsu4ju19j7132@corp.supernews.com...
> What are the reasons for prohibiting const_cast on pointers to member
> functions?

Standard gives very simple explanation to this in 5.2.11p12, "conversions
between pointers to functions are not covered because such conversions lead
to values whose use causes undefined behavior."

Gene Bushuyev
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: postmast.root.admi.gov@iname.com (blargg)
Date: 1999/09/03
Raw View
In article <rsu4ju19j7132@corp.supernews.com>, <jlund@allaire.com> wrote:

> What are the reasons for prohibiting const_cast on pointers to member
> functions?
> Don't the reasons for using const_cast on other types also apply to function
> pointers (e.g., to use an incorrectly-specified interface in a third-party
> library)?
>
> typedef void (MyClass::*TNonConstMemFun)();
> TNonConstMemFun pFun =
>     const_cast<TNonConstMemFun>(&MyClass::MyConstMemFun);

They are two different types. It is equivalent to

    typedef void (*f_non_const)( int& );
    typedef void (*f_const)( int const& );

These are two different types that can't be interchanged.

If such a conversion were allowed, I don't see how it would be useful
either way. From th f_const to f_non_const would be useless, since f_const
accepts a superset of the types f_non_const accepts. The other way around
would be unsafe, since f_non_const may modify its argument, but the type
of pointer to it would say otherwise, allowing const arguments to be
passed.

Why do you want to do this?


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]