Can user defined numeric literals be immediately f

2019-04-04 14:23发布

This question already has an answer here:

Since C++11, it has been possible to create User Defined Literals. As expected, it's possible to return complex structs from such literals. However, when trying to use such operators as 123_foo.bar():

struct foo {
    int n;
    int bar() const { return n; }
};

constexpr foo operator ""_foo(unsigned long long test)
{
    return foo{ static_cast<int>(test) };
}

int main() {
    return 123_foo.bar();
}

GCC and Clang reject it, saying they can't find an operator""_foo.bar. MSVC accepts it. If I instead write 123_foo .bar(), all three compilers accept it

Who is right here? Is 123_foo.bar() ever valid?


Some extra information:


I'm inclined to believe that this is a GCC and Clang bug, as . is not part of a valid identifier.

1条回答
等我变得足够好
2楼-- · 2019-04-04 15:14

TLDR Clang and GCC are correct, you can't write a . right after a user defined integer/floating literal, this is a MSVC bug.

When a program gets compiled, it goes through 9 phases of translations in order. The key thing to note here is lexing (seperating) the source code into tokens is done before taking into consideration its semantic meaning.

In this phase, maximal munch is in effect, that is, tokens are taken as the longest sequence of characters that is syntactically valid. For example x+++++y is lexed as x ++ ++ + y instead of x + ++ ++ y even if the former isn't semantically valid.

The question is then what is the longest syntactically valid sequence for 123_foo.bar. Following the production rules for a preprocessing number, the exact sequence is

pp-number → pp-number identifier-nondigit → ... → pp-number identifier-nondigit³ →
pp-number nondigit³ → pp-number . nondigit³ → ... → pp-number nondigit⁴ . nondigit³ →
pp-number digit nondigit⁴ . nondigit³ → ... → pp-number digit² nondigit⁴ . nondigit³ →
digit³ nondigit⁴ . nondigit³

Which resolves to 123_foo.bar as seen in the error message

查看更多
登录 后发表回答