7

In the following program the global variable isCompleteType<Apple> is initialized differently by clang and gcc (live on godbolt.org):

template <class T>
constexpr bool IsCompleteTypeHelper (decltype (sizeof (T))) { return true; }

template <class T>
constexpr bool IsCompleteTypeHelper (...)                   { return false; }

template <class T>
bool isCompleteType = IsCompleteTypeHelper<T> (0);


class Apple;


int main ()
{
    return isCompleteType<Apple>;
}


class Apple {};
  • Clang 10.0.0 initializes isCompleteType<Apple> to true.
  • Gcc 9.3 initializes isCompleteType<Apple> to false.

Since the definition of Apple – which could make the variable true – is after the instantiation of isCompleteType, I concluded that the compilers do the following when they initialize the variable.

  • Clang considers the whole translation unit.
  • Gcc considers only the code above the instantiation.

Which compiler is right? Why? Could you quote the standard?

Remark: My question is different than this question. See the comments.

Dr. Gut
  • 2,053
  • 7
  • 26
  • I think this doesn't directly answer your question, but that it'll still interest you: https://stackoverflow.com/a/22773745/2330673 – Oppen Apr 05 '20 at 16:46
  • 3
    Does this answer your question? [Expecting different types depending of point of instantiation](https://stackoverflow.com/questions/52264984/expecting-different-types-depending-of-point-of-instantiation) – Davis Herring Apr 05 '20 at 19:23
  • I don't think that link quite answers this question. They are two different problems; in the linked question there's two instantiation points. In this, there's only one. – ChrisMM Apr 05 '20 at 22:25
  • @DavisHerring: The linked question does not answer this. That question is about class templates, this is about variable templates. And even if that question would be about (constexpr) variable tamplates, the (only) answer does not say wherther both `static_assert`s should pass or both should fail according to the standard, i.e. the whole translation unit should be considered, or just the part above the instantiation. It only implies, that the two `static_assert`s will work the same way. Could you please remove the delete request from my question? – Dr. Gut Apr 06 '20 at 00:32
  • 1
    @ChrisMM: Of course there are multiple points of instantiation here—for the *function* template `IsCompleteTypeHelper`. – Davis Herring Apr 06 '20 at 00:37
  • @Dr.Gut: It’s not a *delete* vote, and I can’t rescind it, although it will expire on its own if no one else votes. You’re right that they’re not quite the same; I was mostly going for Barry’s *answer* there. Sorry to have not picked the best of the related questions; hopefully one of the various other interlinked questions about multiple points of instantiation will be helpful. – Davis Herring Apr 06 '20 at 00:48
  • 1
    @DavisHerring: Sorry, I meant a *close* vote. Why is this question voted for closing by two people? Why is a second person directing me to [this question](https://stackoverflow.com/questions/52264984/expecting-different-types-depending-of-point-of-instantiation) *after* I explained that it does not answer my question. **We are most probably facing a clang bug**. I just need to be more sure. With someone's help who is more familiar with the standard, we can figure this out. – Dr. Gut Apr 06 '20 at 18:26
  • @Dr.Gut: You are not facing any bug, and several of us are reasonably familiar with the standard. Do you understand the issue with the function template in your question? – Davis Herring Apr 06 '20 at 18:42
  • @DavisHerring: No, I do not. Is there an issue with it? As for rescinding the close vote: [this meta question](https://meta.stackexchange.com/a/949) says you can undo a close vote. Am I misunderstanding something? – Dr. Gut Apr 06 '20 at 18:46
  • @Dr.Gut: See my other comment about the function template, then. And now I know that I can, thanks (and did so, but only because I picked the wrong duplicate); that interface doesn’t exist in the first place I looked. – Davis Herring Apr 06 '20 at 18:58
  • @DavisHerring: I have read that comment. Do you mean [this rule](http://eel.is/c++draft/temp#point-7.sentence-4)? You mean which overload of `IsCompleteTypeHelper`? I think you meant the first. That overload either instantiates or fails due to substitution failure. So I see no two different POIs where this function would have different meanings with regard to the one definition rule. I might be wrong, my understanding is not complete here. Which interface does not exist? I do not get it. – Dr. Gut Apr 06 '20 at 19:10
  • @Dr.Gut: Yes, that rule, but also the first (long) sentence in that paragraph; it has a point of instantiation at the end of the translation unit. (The “interface” was just the retract-close-vote button.) – Davis Herring Apr 06 '20 at 19:43
  • @DavisHerring: As I see it, for the first overload of `IsCompleteTypeHelper` there are two POIs: one in `main`, and one at the end of the file. The first POI fails to instantiate the function template, the second succeeds, thus only the second yields a function definition. That is only one function definition. To violate ODR, you have to have at least two. So ODR is not violated. What do you think? And thanks for removing the close vote. – Dr. Gut Apr 06 '20 at 20:51
  • @Dr.Gut: You’re not actually violating the ODR, but you are changing the meaning of the instantiation (by making it succeed), and that’s enough. – Davis Herring Apr 06 '20 at 20:58
  • @DavisHerring: Why do you think, that this is enough? The [quoted sentence](http://eel.is/c++draft/temp#point-7.sentence-4) in the standard clearly states "according to the one-definition rule". – Dr. Gut Apr 06 '20 at 21:08
  • @Dr.Gut: (Why link the same sentence again?) It uses the ODR to compare putative instantiations, not to count them. – Davis Herring Apr 06 '20 at 21:52
  • @DavisHerring: How does one know that this is about putative instantiations? In my reading this is about actual instantiations. (I linked the sentence again for others to make the comment clear without needing to look 4 comments above. Sorry for misleading you.) – Dr. Gut Apr 07 '20 at 17:44
  • @Dr.Gut: The standard is miserably unclear about many aspects of instantiation; some of what I have said is as much interpolation as interpretation. (I should have called that out, but it’s hard to remember exactly where the boundary is between memory and conjecture.) There *are* mentions of [instantiating *declarations*](http://eel.is/c++draft/temp.inst#10) separately from definitions, and C++20 adds (in an odd place) an explicit statement that [completeness is measured at the point of instantiation](http://eel.is/c++draft/module.reach#4). – Davis Herring Apr 07 '20 at 18:59

0 Answers0