9

Suppose we have the following program:

template <class T, T n1, T n2>
struct Probe { 
    static const int which = 1;
};

template <class T, T n>
struct Probe<T, n, n> { 
    static const int which = 2;
};


int i = 123;

const int myQuestion = Probe<int&, i, i>::which;

I am pretty sure, that myQuestion should be 2 regardless of the version of C++ standard, but compilers disagree upon it. MSVC and clang say that it is 2 until C++14, and 1 since C++17. See the demo. What is the truth?

My investigation so far:

  • I have found one relevant sentence in the C++ standard. It was there in C++11, C++14, C++17 and C++20. It did not change.
  • If you remove the parameter T from the example code, all compilers agree, that myQuestion is 2. Demo.
Dr. Gut
  • 2,053
  • 7
  • 26
  • Shouldn't `i` be `const` at least? – πάντα ῥεῖ Feb 07 '22 at 16:56
  • 3
    First `i` should be a **constant expression** when passing as template argument. Add `constexpr` or `const` for it. – Jason Feb 07 '22 at 16:58
  • Looks like the program is ill-formed since `i` is not a constant expression in your case. If you make it a constant expression, the program will no longer compile in any version. – Jason Feb 07 '22 at 17:01
  • Definitely an interesting Q. References are meant to be translucent in the type system. Not sure how that may interplay with template equivalence checks however. – StoryTeller - Unslander Monica Feb 07 '22 at 17:02
  • 2
    @AnoopRana - it's not ill-formed. For god's sake, it's a [mre], check it before commenting. A **reference** to an object with static storage duration is permissable in constant expressions, **even when** the referent is not const. – StoryTeller - Unslander Monica Feb 07 '22 at 17:04
  • @AnoopRana - Read the error carefully then. It is claiming, `i` **is const**. Wrong indeed, but adding const won't solve *that*. – StoryTeller - Unslander Monica Feb 07 '22 at 17:09
  • @AnoopRana Same error with contexpr/const int&: https://godbolt.org/z/a5Mrj4M53 – Artyer Feb 07 '22 at 17:11
  • @AnoopRana - And you missed the point of mine. It already is valid in constant expressions. – StoryTeller - Unslander Monica Feb 07 '22 at 17:13
  • @StoryTeller-UnslanderMonica I think you're right[in which case i'll delete my comments] but i can't find the exact statement that you quoted: *"A reference to an object with static storage duration is permissable in constant expressions, even when the referent is not const"*. Can you put a link here for me? – Jason Feb 07 '22 at 17:28
  • @AnoopRana - https://timsong-cpp.github.io/cppwp/n4868/expr.const#11 should have the gist of it. – StoryTeller - Unslander Monica Feb 07 '22 at 17:39
  • @StoryTeller-UnslanderMonica Ok then shouldn't [this](https://godbolt.org/z/h7ajqhnan) work without error? As you said, [here](https://godbolt.org/z/h7ajqhnan) we have a reference `ref` to an object `i` with static storage duration. Then `ref` can be used as size of an array. Am i missing something? – Jason Feb 07 '22 at 17:44
  • 3
    This is a duplicate of https://stackoverflow.com/questions/37369129 but can't be targetted because it doesn't have an upvoted/accepted answer. – cigien Feb 07 '22 at 17:48
  • 1
    @AnoopRana - Accessing the object's value in a constant expression requires it to satisfy additional constraints so the value is usable (in that case it should be constexpr indeed). Referring to the object alone (like in the OP, on surface level) doesn't require anything from the value. – StoryTeller - Unslander Monica Feb 07 '22 at 18:32
  • @cigien: It's not a good idea to mark my question as a duplicate of that [long question](https://stackoverflow.com/questions/37369129). Even if my question is answered there, since it's so long, it would be difficult for the readers to extract information from that. – Dr. Gut Feb 19 '22 at 08:07
  • Ok, I don't have an issue with that. It *is* a duplicate, but it's not exactly a question that gets asked a lot, so it's not a big deal to leave it open. I wouldn't dispute the closure either, i.e. I'm fine not voting either way. – cigien Feb 19 '22 at 13:57

0 Answers0