On 09/25/2017 02:03 AM, Martin Sebor wrote:

> +a @option{-Wincompatible-pointer-types} warning for mismatches.  To suppress
> +a warning for the necessary cast from a pointer to the implementation member
> +function to the type of the corresponding non-member function use the
> +@option{-Wno-pmf-conversions} option.  For example:

FWIW, it seems odd to me to tell users they need to suppress warnings, when
the compiler surely could provide better/safer means to avoid needing
to use the reinterpret_cast hammer.   See below.

> +
> +@smallexample
> +class S
> +@{
> +private:
> +  int debug_impl (int);
> +  int optimized_impl (int);
> +
> +  typedef int Func (S*, int);
> +
> +  static Func* resolver ();
> +public:
> +
> +  int interface (int);
> +@};
> +
> +int S::debug_impl (int) @{ /* @r{@dots{}} */ @}
> +int S::optimized_impl (int) @{ /* @r{@dots{}} */ @}
> +
> +S::Func* S::resolver ()
> +@{
> +  int (S::*pimpl) (int)
> +    = getenv ("DEBUG") ? &S::debug_impl : &S::optimized_impl;
> +
> +  // Cast triggers -Wno-pmf-conversions.
> +  return reinterpret_cast<Func*>(pimpl);
> +@}
> +

If I were writing code like this, I'd write a reinterpret_cast-like
function specifically for pointer-to-member-function to free-function
casting, and only suppress the warning there instead of disabling
the warning for the whole translation unit.  Something like:

#include <type_traits>

template<typename T> struct pmf_as_func;

template<typename Ret, typename S, typename... Args>
struct pmf_as_func<Ret (S::*) (Args...)>
{
  typedef Ret (func_type) (S *, Args...);
  typedef S struct_type;
};

template<typename Pmf>
typename pmf_as_func<Pmf>::func_type *
pmf_as_func_cast (Pmf pmf)
{
  static_assert (!std::is_polymorphic<typename 
pmf_as_func<Pmf>::struct_type>::value,
                 "");
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpmf-conversions"
  return reinterpret_cast<typename pmf_as_func<Pmf>::func_type *> (pmf);
#pragma GCC diagnostic pop
}


and then write:
 return pmf_as_func_cast (pimpl);

instead of:
  return reinterpret_cast<Func*>(pimpl);

The point being of course to make it harder to misuse the casts.

But that may be a bit too much for the manual.  

It also wouldn't work as is with C++03 (because variatic templates).
Which leads me to think that if GCC guarantees this cast works, then
it'd be nice to have GCC provide it (like a __pmf_as_func_cast function)
as builtin.  Then it'd work on C++03 as well, and the compiler of course
can precisely validate whether the cast is valid.  (It's quite possible
that there's a better check than is_polymorphic as I've written above.)

Just a passing thought.

Thanks,
Pedro Alves

Reply via email to