c++ - Example in C++23 standard doesn't work in gcc? - Stack Overflow

In the unqualified name lookup, the standard gives the example 1.struct T1 { struct U { int i; }; };s

In the unqualified name lookup, the standard gives the example 1.

struct T1 { struct U { int i; }; };
struct T2 { };
struct U1 {};
struct U2 {};

struct B {
  using T = T1;
  using U = U1;
  operator U1 T1::*();
  operator U1 T2::*();
  operator U2 T1::*();
  operator U2 T2::*();
};

template<class X, class T>
int g() {
  using U = U2;
  X().operator U T::*();                // #1, searches for T in the scope of X first
  X().operator U decltype(T())::*();    // #2
  return 0;
}
int x = g<B, T2>();                     // #1 calls B​::​operator U1 T1​::​*
                                        // #2 calls B​::​operator U1 T2​::​*

An unqualified name that is a component name ([expr.prim.id.unqual]) of a type-specifier or ptr-operator of a conversion-type-id is looked up in the same fashion as the conversion-function-id in which it appears. If that lookup finds nothing, it undergoes unqualified name lookup; in each case, only names that denote types or templates whose specializations are types are considered.

From the standard, it seems that the unqualified name U and T in operator U T::* shall be looked up in the same way as operator U T::*, i.e. looked up in the class scope B, so that the first call should be operator U1 T1::*. While the expression decltype(T()) will be instantiated to be T2, the second call should be operator U1 T2::*().

It shocks me so that I made an experiment by adding codes below and compiling it:

#include <iostream>

B::operator U1 T1::*()
{
    std::cout << __func__ << std::endl;
    return nullptr;
}
B::operator U1 T2::*()
{
    std::cout << __func__ << std::endl;
    return nullptr;
}
B::operator U2 T1::*()
{
    std::cout << __func__ << std::endl;
    return nullptr;
}
B::operator U2 T2::*()
{
    std::cout << __func__ << std::endl;
    return nullptr;
}
int main() {}

However, the result is

operator U2 T2::*
operator U2 T2::*

instead of by the standard

operator U1 T1::*
operator U1 T2::*

Why the behavior differs with standard? I find no Defect Report about this.

My g++ version is
g++.exe (x86_64-win32-seh-rev1, Built by MinGW-Builds project) 14.2.0

In the unqualified name lookup, the standard gives the example 1.

struct T1 { struct U { int i; }; };
struct T2 { };
struct U1 {};
struct U2 {};

struct B {
  using T = T1;
  using U = U1;
  operator U1 T1::*();
  operator U1 T2::*();
  operator U2 T1::*();
  operator U2 T2::*();
};

template<class X, class T>
int g() {
  using U = U2;
  X().operator U T::*();                // #1, searches for T in the scope of X first
  X().operator U decltype(T())::*();    // #2
  return 0;
}
int x = g<B, T2>();                     // #1 calls B​::​operator U1 T1​::​*
                                        // #2 calls B​::​operator U1 T2​::​*

An unqualified name that is a component name ([expr.prim.id.unqual]) of a type-specifier or ptr-operator of a conversion-type-id is looked up in the same fashion as the conversion-function-id in which it appears. If that lookup finds nothing, it undergoes unqualified name lookup; in each case, only names that denote types or templates whose specializations are types are considered.

From the standard, it seems that the unqualified name U and T in operator U T::* shall be looked up in the same way as operator U T::*, i.e. looked up in the class scope B, so that the first call should be operator U1 T1::*. While the expression decltype(T()) will be instantiated to be T2, the second call should be operator U1 T2::*().

It shocks me so that I made an experiment by adding codes below and compiling it:

#include <iostream>

B::operator U1 T1::*()
{
    std::cout << __func__ << std::endl;
    return nullptr;
}
B::operator U1 T2::*()
{
    std::cout << __func__ << std::endl;
    return nullptr;
}
B::operator U2 T1::*()
{
    std::cout << __func__ << std::endl;
    return nullptr;
}
B::operator U2 T2::*()
{
    std::cout << __func__ << std::endl;
    return nullptr;
}
int main() {}

However, the result is

operator U2 T2::*
operator U2 T2::*

instead of by the standard

operator U1 T1::*
operator U1 T2::*

Why the behavior differs with standard? I find no Defect Report about this.

My g++ version is
g++.exe (x86_64-win32-seh-rev1, Built by MinGW-Builds project) 14.2.0

Share Improve this question asked Mar 12 at 16:22 BlowingWindBlowingWind 1831 silver badge5 bronze badges 5
  • godbolt./z/69ex4Gjhb it is expected that program prints 38: B::operator U2 T1::*() instead of 38: B::operator U2 T2::*() – Marek R Commented Mar 12 at 16:37
  • 1 you usually need to wait about 5 years before a standard is implemented by enough compilers that you can safely use it. this year we finally got C++20 ... 3 more years for C++23 – Ahmed AEK Commented Mar 12 at 19:24
  • 1 @AhmedAEK And even for C++20, it is not really yet time. Module system is still in progress or buggy on all major compilers. – prapin Commented Mar 12 at 20:56
  • @AhmedAEK Since it's nearly total green when checking C++23 compiler support in cppreference, I thought gcc must have implemented these minor changes...(because it only affects lookup for conversion operator) – BlowingWind Commented Mar 13 at 5:26
  • Side note: Just noticed my previous comment didn't actually LINK to the table I wrote about. So here we go again! A handy table of what does and what does not yet work in GCC. Even the most recent GCC releases do not fully support C++23 (or C++20, for that matter). Sometimes you run into one of those holes. – user4581301 Commented Mar 13 at 20:33
Add a comment  | 

1 Answer 1

Reset to default 6

This has to do with the fact that lookup for dependent conversion-type-ids was never properly specified prior to C++23; see CWG1500. The rule you cite was added by P1787R6, which completely overhauled the specification of name lookup in the standard. Because so many changes were made, it will take a while for GCC to finish implementing all of them.

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744740614a4591004.html

相关推荐

  • c++ - Example in C++23 standard doesn&#39;t work in gcc? - Stack Overflow

    In the unqualified name lookup, the standard gives the example 1.struct T1 { struct U { int i; }; };s

    10小时前
    50

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信