Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.3k views
in Technique[技术] by (71.8m points)

calling typeid on template difference between GNU C++ and MSVC problem

I am trying to port a code that should work and compile on both Linux (GCC/C++) and windows (MSVC) however the following line is giving me trouble

template <class TDerived>
struct Event
{
    inline static std::string eventId = typeid(TDerived).name();
};

struct Derived : public Event<Derived>
{
    Derived() = default;

};

The code uses typeid and name() to set the event name,

In GNU/C++ it compiles properly in both Linux and Apple (Clang), and even in Windows using MingW. but in windows using MSVC it gives the following error

error C2027: use of undefined type 'Derived'
message : see declaration of 'Derived'
message : see reference to class template instantiation 'Event<Derived>' being compiled

basically because Derived is incomplete at this time and is not visible in the Event scope. But why does GNU/GCC, MingW and Clang succesfuly compiled it? Do we have a workaround in MSVC (Visual Studio)?

question from:https://stackoverflow.com/questions/65935903/calling-typeid-on-template-difference-between-gnu-c-and-msvc-problem

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

C++ standard says:

[expr.typeid]

When typeid is applied to a type-id ... If the type of the type-id is a class type or a reference to a class type, the class shall be completely-defined.

As far as I can tell, the class isn't completely-defined in that context. If that interpretation is correct, then the rule is violated and the program is ill-formed. That said, I'm not 100% sure since template instantiation makes the rules quite complex.

But why does GNU/GCC, MingW and Clang succesfuly compiled it?

For whatever reason, their implementation can apparently cope with non-completely defined classes. They aren't required to successfully compile it. Technically they do not conform to the standard if they do not provide a diagnostic message (assuming the the interpretation of program being ill-formed is correct).

Do we have a workaround in MSVC (Visual Studio)?

Defining a non-inline static member seems to work in godbolt:

template <class TDerived>
struct Event
{
    static std::string eventId;
};

template <class TDerived>
std::string Event<TDerived>::eventId = typeid(TDerived).name();

Note that the name is implementation defined and is not going to be the same across all language implementations.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...