6

The following code snippet compiles only if I explicitly specify the template argument T for the Base struct in Derived ctor:

template <class T>
struct Base
{
    Base(int) {}
};

template <class T>
struct Derived : Base<T>
{
    Derived(int i) : Base<T>(i) {}
};

If I call Base(i) instead of Base<T>(i) - it doesn't work. Why can't compiler determine that Base is actually Base<T> (because I derive from Base<T>)? Is this requirement made intentionally?

undermind
  • 1,779
  • 13
  • 33
  • How would the compiler distinguish that from a non template `class Base` or function otherwise? – πάντα ῥεῖ Oct 03 '18 at 17:39
  • @πάνταῥεῖ But how can we call non-template `class Base` ctor if we derive from `Base`? – undermind Oct 03 '18 at 17:41
  • 1
    In my experience, MSVC accepts `Derived(int i) : Base(i) {}`. I don't trust it though. – alter_igel Oct 03 '18 at 17:41
  • @alterigel Actually, the question appeared from this MSVC behavior - in non-conformant mode it accepts omitting ``, but in conformant - no :) – undermind Oct 03 '18 at 17:42
  • Closest dupe I can find is [this](https://stackoverflow.com/questions/7969048/are-template-arguments-required-everywhere-when-mentioning-a-template-base-class). TL;DR: Dependent names don't become injected class names – NathanOliver Oct 03 '18 at 17:54
  • 2
    The fix is to write `Derived::Base`---this forces `Base` to be looked up in the dependent base class, finding the injected-class-name. – Brian Bi Oct 03 '18 at 17:56
  • Similar or dupe: https://stackoverflow.com/q/21118605/560648 tl;dr it's supposed to work but often doesn't. What compiler are you using? – Lightness Races in Orbit Oct 03 '18 at 17:56
  • @NathanOliver Interesting contradiction to the findings of 21118605! – Lightness Races in Orbit Oct 03 '18 at 17:57
  • @NathanOliver Oh I suppose not as in my case the base wasn't a dependant name – Lightness Races in Orbit Oct 03 '18 at 17:58
  • @LightnessRacesinOrbit That's my guess. Since it depends on the template type from the derived class it doesn't get injected. I'm not really finding anything else about it and trying to parse the standard is going to take me a bit. I think I'll leave it for others. – NathanOliver Oct 03 '18 at 18:00
  • i dont understand why the answer i gave below is being downvoted but.. it would help if you guys leave a comment. as for your question. you are doing a static polymorphisim. how do you expect compiler to figure it all out because you derived from base class – Yucel_K Oct 03 '18 at 18:58
  • and even if compiler A did. how about the compiler B the next person whos going to use ur code? – Yucel_K Oct 03 '18 at 18:58
  • @Yucel_K I did not downvote you. But I have tried to understand you. I can't. I think your wording is realy special. I suppose you could try to give an other answer. I you refer to [this paragraph](http://eel.is/c++draft/temp.res#10) you could use a standardized, probably more widely accepted wording. – Oliv Oct 03 '18 at 19:07
  • @undermind `But how can we call non-template class Base`. what you mean by that? – Yucel_K Oct 03 '18 at 19:14
  • @Oliv i dont mind people downvoting. I mind people downvoting without telling what's wrong with it. – Yucel_K Oct 03 '18 at 19:21
  • @Yucel_K I meant that if we call `Base(i)` in the `Derived`'s ctor member initializer list, then it unambiguously means `Base(i)`, doesn't it? It was a reply to the top comment, where was mentioned that without `` compiler can misinterpret `Base(i)` as a call to non-template class `Base`. – undermind Oct 03 '18 at 19:27
  • Base is a template class. it becomes a template class the moment you added the template . (im not sure but perhaps some compilers can remove the template decleration `template ` ) . just have a struct Base and remove the Derived class. and then try to instantiate a non template Base class. your compiler would more likely complain still. – Yucel_K Oct 03 '18 at 19:31
  • @Yucel_K Well, I just thought about that `Derived` class can have a member variable `Base` [like this](https://wandbox.org/permlink/rgKejgApL09LCkMq), then we need to distinguish somehow between member variable and base class. – undermind Oct 03 '18 at 19:32
  • im pretty sure you can not do that (if not all , many compilers. can't handle the ambiguity during compilation). if you want to derive from a base class that is not a template, you can still do it, but slightly differently. I personally like this mainly because it still allows me to have virtual functions on base class https://blog.feabhas.com/2014/06/template-inheritance/ (Deriving from a non-template base class) – Yucel_K Oct 03 '18 at 19:40
  • 2
    Injected class name are in the scope of the class. So are class member names. The general rule is that dependent base scope names are not visible at the point of definition of the derived template class. It is true that whatever `T` the injected class name of `Base` is `Base` so compilers could infer that `Base` designate the injected class name of `Base`. But that would be an other special rule. My opinion is that the c++ language has enough corner cases, and special rules which hurts coherency. So I am glad to see there is no special treatment for dependent base class injected name. – Oliv Oct 03 '18 at 20:05
  • @Oliver I agree. which all boils down how the compiler designed to handle the translation phase of the source code during compilation. this would then clearly explain why `Derived(int i) : Base(i)` would work. Unfortunately, i don't have any knowledge other than the terminology of translation phase. – Yucel_K Oct 03 '18 at 20:19
  • @undermind I notice this still has not received an answer. Would you mind if I add the [tag:language-lawyer] tag and start a bounty on this? – NathanOliver Nov 05 '18 at 20:17
  • @NathanOliver It seems that [Oliv's comment](https://stackoverflow.com/posts/comments/92203005) gives a reasonable conclusion: compiler _could_ infer that `Base` is `Base`, but it would be one more special rule, really no great need to introduce it to language. But, if you feel there is something more here, you're welcome. – undermind Nov 06 '18 at 14:27
  • @undermind I'm good with the comment. I just had this marked as a favorite and came back to it yesterday to see if an answer was ever posted. I'll just leave it be. – NathanOliver Nov 06 '18 at 14:29

0 Answers0