-1

1

#include<type_traits>
#include<iostream>
using namespace std;

enum class Widget;
using UType = underlying_type_t<Widget>;
UType getWidget();

int main() {
    cout<<getWidget();
    cout<<static_cast<int>(Widget::a);
    return 0;
}

UType getWidget() {
    return static_cast<UType<Widget>>(Widget::a);
}

enum class Widget {
    a, b, c
};

2

#include<iostream>
#include<type_traits>
using namespace std;

template<typename T>
using UType = underlying_type_t<T>;

enum class Widget;

template<typename T>
UType<T> getWidget();

int main() {
    cout<<getWidget<Widget>();
    //cout<<static_cast<int>(Widget::a);
    return 0;
}

template<typename T>
UType<T> getWidget() {
    return static_cast<UType<Widget>>(Widget::a);
}


enum class Widget {
    a, b, c
};

When I used Widget::a in main, compiler failed because of "Undefined identifier Error". But, when I called GetWidget, this code was compiled. What is difference in two situations?

---2 is working if I use getWidget(). but 1 isn't. ---compiler : visual studio 2019 iso c++14 standard ---error message :

  1. c2027 : use of undefined type 'Widget'

  2. C2065 : 'a' : undeclared identifier

  • 1
    `But, when I called GetWidget, this code was compiled. What is difference in two situations?` Could you please post a separate code snippet with the code that was compiled? You call the function in the code you posted, and it did not compile - there's a contradiction. I do not believe `UType` given `UType = underlying_type_t;` would compile. Are you sure you are using this source file? – KamilCuk Jun 12 '21 at 08:40

1 Answers1

1

You need to define enum class Widget before you can use any of the enumerators (Widget::a). You have the definition below everything else, where it invisible to everything else and therefore useless. The declaration is visible, but a mere declaration is not enough to use the enumerators. It is only enough to use the name of the enumeration itself (Widget).

MSVC does not detect the error in getWidget because its handling of templates is not standards compliant. Its implementation of the two-phase lookup is incomplete and is not enabled by default. If you enable it with a compiler switch, it is still incomplete. It seems to be broken for qualified names, which are not looked up in the first phase. That is, if you write x::y in a template, MSVC looks up x in the first phase (and complains if it is not defined), but ignores y. Other compilers do not have this bug.

If you make getWidget a non-template, which it should have been in the first place, MSVC will complain.

n. m. could be an AI
  • 112,515
  • 14
  • 128
  • 243
  • if so, why getWidget() is worked well? Widget is defined blow getWidget() definition.. –  Jun 12 '21 at 08:39
  • @yeongro [it didn't](https://godbolt.org/z/djh5TPrW7). If you have a version where `getWidget` works, post a [mcve] together with a complete and unedited set of compiler messages. – n. m. could be an AI Jun 12 '21 at 08:42
  • Can I post format like compiler : visual studio 2019 iso c++ 14 standard, not error message(call getWidget), error messages(call a in main), C2027-Use undefined type Widget and 'a' is undefined identifier? –  Jun 12 '21 at 09:03
  • @yeongro please edit your question and include the exact source file(s) and the **complete unedited error messages** for each separate run of the compiler. Error messages should be formatted as code. – n. m. could be an AI Jun 12 '21 at 09:07
  • I can't find how to upload code.. sorry, but, code block 2 is same code.. –  Jun 12 '21 at 09:24
  • @yeongro No worries, I have updated my answer to explain the problem with MSVC. – n. m. could be an AI Jun 12 '21 at 09:32
  • Thank you very very much!! :) have a good weekend!! –  Jun 12 '21 at 12:18