3

Disclaimer: Maybe what I'm trying to do is prohibited by the standard, if so please let me know.

I'm trying to take the type of a virtual method (pointer) with decltype within the scope of the class defining the method. This works fine with GCC, but hard crashes Visual Studio 2013:

class foo
{
public:
    virtual void bar() = 0;

    // typedef decltype(&foo::bar) bar_pointer; // crashes VS2013 (error C1001: An internal error has occurred in the compiler)

};
typedef decltype(&foo::bar) bar_pointer; // works fine with VS2013

For various reasons I need the type within the class, so I'm trying to work around this crash. Interestingly enough, the following compiles with VS2013:

class foo
{
public:
    virtual void bar() = 0;

    typedef decltype(foo::bar) bar_pointer; // works in VS2013, GCC complains(invalid use of non-static member function)
};

Here, the type of bar_pointer comes out as void __thiscall foo::(void). Doesn't make much sense to me, I guess this is some erroneous type. Yet I tried to transform this type to a valid method pointer type by passing it to a template specialization which extracts return type and parameter types. But it seem like this weird type doesn't match any specialization I could come up with.

Does anyone have an idea what's going on here or can think of a way to workaround this issue?

UPDATE:

Seem like this is not directly related to decltype, but to unevaluated contexts in general. The following also crashes:

class foo
{
public:
    virtual void bar() = 0;

    static const size_t test = sizeof(&foo::bar);
};
Horstling
  • 2,131
  • 12
  • 14
  • "For various reasons I need the type within the class" Can you elaborate? This looks to be an XY problem. – themagicalyang Nov 11 '16 at 09:16
  • Maybe you should add address operator `&` in second sample. – Albjenow Nov 11 '16 at 09:18
  • @themagicalyang: It's about a static reflection library in which a meta type describing the methods of a class is definied within the class. – Horstling Nov 11 '16 at 09:20
  • Just for curiosity (ignore if it would works but I guess the answer): have you tried to use `using` statement instead `typedef` ? – Gonmator Nov 11 '16 at 09:21
  • @Albjenow: You mean decltype(&foo:bar)? Then it is the same as the first sample (which crashes). – Horstling Nov 11 '16 at 09:21
  • Have tried to replace `bar_pointer` with `typedef void foo::(*bar_pointer)();` to work around `decltype`? – Franck Nov 11 '16 at 09:22
  • @Horstling How good is the `decltype` support in VS2013 ? – Arunmu Nov 11 '16 at 09:23
  • @Gonmator: No change when using `using` – Horstling Nov 11 '16 at 09:25
  • The one with `&` works for me with GCC independent of the place of the `typedef`. – Albjenow Nov 11 '16 at 09:26
  • @Frank: `typedef void (foo::*bar_pointer)();` works, but I need to deduce the type from the method. @Arunmu: `decltype` support is complete in VS2013 afaik (except for SFINAE issuse), but obviously there are still some bugs – Horstling Nov 11 '16 at 09:26
  • Related: [VC++ Internal Compiler Error](http://stackoverflow.com/questions/1091662/vc-internal-compiler-error) – Albjenow Nov 11 '16 at 09:32
  • How about creating a nullptr and asking for the return value of the function? `decltype( ( ( foo* )nullptr )->bar() )` – Trevir Nov 11 '16 at 09:38
  • @Trevir: Doesn't work because `foo` is still a incomplete type at this point. – Horstling Nov 11 '16 at 09:43

1 Answers1

0

First of all, it works fine with GCC/Clang:

struct Foo {
    virtual void bar() = 0;
    using baz = decltype(&Foo::bar);
};

So it looks like an MSVC++ bug/pecularity (member function pointer type depends on class properties). One way to work that around is to declare virtual class "interface" ahead:

struct IFoo {
    virtual void bar() = 0;
};
struct Foo : public virtual IFoo {
    using baz = decltype(&Foo::bar); // note, it works with Foo member function pointer now
};
Dmitry
  • 1,230
  • 10
  • 19