Why won't this compile without a default constructor?












71















I can do this:



#include <iostream>

int counter;

int main()
{
struct Boo
{
Boo(int num)
{
++counter;
if (rand() % num < 7) Boo(8);
}
};

Boo(8);

return 0;
}


This will compile fine, my counter result is 21. However when I try to create the Boo object passing the constructor argument instead of an integer literal I get a compile error:



#include <iostream>

int counter;

int main()
{
struct Boo
{
Boo(int num)
{
++counter;
if (rand() % num < 7) Boo(num); // No default constructor
// exists for Boo
}
};

Boo(8);

return 0;
}


How is a default constructor called in the second example but not in the first example? This is error I get on Visual Studio 2017.



On the online C++ compiler onlineGDB I get the errors:



error: no matching function for call to ‘main()::Boo::Boo()’
if (rand() % num < 7) Boo(num);

^
note: candidate expects 1 argument, 0 provided









share|improve this question




















  • 2





    @NeilButterworth I'm aware of the most vexing parse, but it didn't strike me as a case of it because I was passing local variable to the constructor, and thought that this was not ambiguous because I didn't see it as ambiguous when passing a local variable identifier. user10605163's answer is enlightening as it explains that types or non-types are not used in disambiguation. I don't know anything about the upvotes other than that I upvoted both answers as I found them helpful. You can close this if this is dupe.

    – Zebrafish
    Dec 16 '18 at 23:21






  • 9





    @NeilButterworth: "Any problems with these proposals?" Because the most-vexing parse is usually presented as a competition between creating a temporary and declaring a function. This is instead treated as creating a variable. Similar idea, similar resolution, but ultimately a different source.

    – Nicol Bolas
    Dec 16 '18 at 23:54






  • 4





    @Nicol "Any problems with these proposals?" - um, what? Where?

    – Neil Butterworth
    Dec 17 '18 at 0:12








  • 4





    I upvoted the question and answers because I learned something new. I was aware of the most-vexing parse, and this manifestation of it was different enough from previous ones I've seen. The answers were helpful, and the workarounds were interesting.

    – Eljay
    Dec 17 '18 at 1:43






  • 11





    @user202729: But they aren't. Simply saying "most vexing parse" doesn't answer the question. You have to explain how it is a "most vexing parse". And that requires explaining that it's trying to declare a variable in this case, but a function in other cases. Those are different things, for different reasons, and thus have to be different answers.

    – Nicol Bolas
    Dec 17 '18 at 14:36


















71















I can do this:



#include <iostream>

int counter;

int main()
{
struct Boo
{
Boo(int num)
{
++counter;
if (rand() % num < 7) Boo(8);
}
};

Boo(8);

return 0;
}


This will compile fine, my counter result is 21. However when I try to create the Boo object passing the constructor argument instead of an integer literal I get a compile error:



#include <iostream>

int counter;

int main()
{
struct Boo
{
Boo(int num)
{
++counter;
if (rand() % num < 7) Boo(num); // No default constructor
// exists for Boo
}
};

Boo(8);

return 0;
}


How is a default constructor called in the second example but not in the first example? This is error I get on Visual Studio 2017.



On the online C++ compiler onlineGDB I get the errors:



error: no matching function for call to ‘main()::Boo::Boo()’
if (rand() % num < 7) Boo(num);

^
note: candidate expects 1 argument, 0 provided









share|improve this question




















  • 2





    @NeilButterworth I'm aware of the most vexing parse, but it didn't strike me as a case of it because I was passing local variable to the constructor, and thought that this was not ambiguous because I didn't see it as ambiguous when passing a local variable identifier. user10605163's answer is enlightening as it explains that types or non-types are not used in disambiguation. I don't know anything about the upvotes other than that I upvoted both answers as I found them helpful. You can close this if this is dupe.

    – Zebrafish
    Dec 16 '18 at 23:21






  • 9





    @NeilButterworth: "Any problems with these proposals?" Because the most-vexing parse is usually presented as a competition between creating a temporary and declaring a function. This is instead treated as creating a variable. Similar idea, similar resolution, but ultimately a different source.

    – Nicol Bolas
    Dec 16 '18 at 23:54






  • 4





    @Nicol "Any problems with these proposals?" - um, what? Where?

    – Neil Butterworth
    Dec 17 '18 at 0:12








  • 4





    I upvoted the question and answers because I learned something new. I was aware of the most-vexing parse, and this manifestation of it was different enough from previous ones I've seen. The answers were helpful, and the workarounds were interesting.

    – Eljay
    Dec 17 '18 at 1:43






  • 11





    @user202729: But they aren't. Simply saying "most vexing parse" doesn't answer the question. You have to explain how it is a "most vexing parse". And that requires explaining that it's trying to declare a variable in this case, but a function in other cases. Those are different things, for different reasons, and thus have to be different answers.

    – Nicol Bolas
    Dec 17 '18 at 14:36
















71












71








71


9






I can do this:



#include <iostream>

int counter;

int main()
{
struct Boo
{
Boo(int num)
{
++counter;
if (rand() % num < 7) Boo(8);
}
};

Boo(8);

return 0;
}


This will compile fine, my counter result is 21. However when I try to create the Boo object passing the constructor argument instead of an integer literal I get a compile error:



#include <iostream>

int counter;

int main()
{
struct Boo
{
Boo(int num)
{
++counter;
if (rand() % num < 7) Boo(num); // No default constructor
// exists for Boo
}
};

Boo(8);

return 0;
}


How is a default constructor called in the second example but not in the first example? This is error I get on Visual Studio 2017.



On the online C++ compiler onlineGDB I get the errors:



error: no matching function for call to ‘main()::Boo::Boo()’
if (rand() % num < 7) Boo(num);

^
note: candidate expects 1 argument, 0 provided









share|improve this question
















I can do this:



#include <iostream>

int counter;

int main()
{
struct Boo
{
Boo(int num)
{
++counter;
if (rand() % num < 7) Boo(8);
}
};

Boo(8);

return 0;
}


This will compile fine, my counter result is 21. However when I try to create the Boo object passing the constructor argument instead of an integer literal I get a compile error:



#include <iostream>

int counter;

int main()
{
struct Boo
{
Boo(int num)
{
++counter;
if (rand() % num < 7) Boo(num); // No default constructor
// exists for Boo
}
};

Boo(8);

return 0;
}


How is a default constructor called in the second example but not in the first example? This is error I get on Visual Studio 2017.



On the online C++ compiler onlineGDB I get the errors:



error: no matching function for call to ‘main()::Boo::Boo()’
if (rand() % num < 7) Boo(num);

^
note: candidate expects 1 argument, 0 provided






c++ constructor scope default-constructor






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Jan 4 at 12:58









iamrajshah

517819




517819










asked Dec 16 '18 at 22:09









ZebrafishZebrafish

3,94411438




3,94411438








  • 2





    @NeilButterworth I'm aware of the most vexing parse, but it didn't strike me as a case of it because I was passing local variable to the constructor, and thought that this was not ambiguous because I didn't see it as ambiguous when passing a local variable identifier. user10605163's answer is enlightening as it explains that types or non-types are not used in disambiguation. I don't know anything about the upvotes other than that I upvoted both answers as I found them helpful. You can close this if this is dupe.

    – Zebrafish
    Dec 16 '18 at 23:21






  • 9





    @NeilButterworth: "Any problems with these proposals?" Because the most-vexing parse is usually presented as a competition between creating a temporary and declaring a function. This is instead treated as creating a variable. Similar idea, similar resolution, but ultimately a different source.

    – Nicol Bolas
    Dec 16 '18 at 23:54






  • 4





    @Nicol "Any problems with these proposals?" - um, what? Where?

    – Neil Butterworth
    Dec 17 '18 at 0:12








  • 4





    I upvoted the question and answers because I learned something new. I was aware of the most-vexing parse, and this manifestation of it was different enough from previous ones I've seen. The answers were helpful, and the workarounds were interesting.

    – Eljay
    Dec 17 '18 at 1:43






  • 11





    @user202729: But they aren't. Simply saying "most vexing parse" doesn't answer the question. You have to explain how it is a "most vexing parse". And that requires explaining that it's trying to declare a variable in this case, but a function in other cases. Those are different things, for different reasons, and thus have to be different answers.

    – Nicol Bolas
    Dec 17 '18 at 14:36
















  • 2





    @NeilButterworth I'm aware of the most vexing parse, but it didn't strike me as a case of it because I was passing local variable to the constructor, and thought that this was not ambiguous because I didn't see it as ambiguous when passing a local variable identifier. user10605163's answer is enlightening as it explains that types or non-types are not used in disambiguation. I don't know anything about the upvotes other than that I upvoted both answers as I found them helpful. You can close this if this is dupe.

    – Zebrafish
    Dec 16 '18 at 23:21






  • 9





    @NeilButterworth: "Any problems with these proposals?" Because the most-vexing parse is usually presented as a competition between creating a temporary and declaring a function. This is instead treated as creating a variable. Similar idea, similar resolution, but ultimately a different source.

    – Nicol Bolas
    Dec 16 '18 at 23:54






  • 4





    @Nicol "Any problems with these proposals?" - um, what? Where?

    – Neil Butterworth
    Dec 17 '18 at 0:12








  • 4





    I upvoted the question and answers because I learned something new. I was aware of the most-vexing parse, and this manifestation of it was different enough from previous ones I've seen. The answers were helpful, and the workarounds were interesting.

    – Eljay
    Dec 17 '18 at 1:43






  • 11





    @user202729: But they aren't. Simply saying "most vexing parse" doesn't answer the question. You have to explain how it is a "most vexing parse". And that requires explaining that it's trying to declare a variable in this case, but a function in other cases. Those are different things, for different reasons, and thus have to be different answers.

    – Nicol Bolas
    Dec 17 '18 at 14:36










2




2





@NeilButterworth I'm aware of the most vexing parse, but it didn't strike me as a case of it because I was passing local variable to the constructor, and thought that this was not ambiguous because I didn't see it as ambiguous when passing a local variable identifier. user10605163's answer is enlightening as it explains that types or non-types are not used in disambiguation. I don't know anything about the upvotes other than that I upvoted both answers as I found them helpful. You can close this if this is dupe.

– Zebrafish
Dec 16 '18 at 23:21





@NeilButterworth I'm aware of the most vexing parse, but it didn't strike me as a case of it because I was passing local variable to the constructor, and thought that this was not ambiguous because I didn't see it as ambiguous when passing a local variable identifier. user10605163's answer is enlightening as it explains that types or non-types are not used in disambiguation. I don't know anything about the upvotes other than that I upvoted both answers as I found them helpful. You can close this if this is dupe.

– Zebrafish
Dec 16 '18 at 23:21




9




9





@NeilButterworth: "Any problems with these proposals?" Because the most-vexing parse is usually presented as a competition between creating a temporary and declaring a function. This is instead treated as creating a variable. Similar idea, similar resolution, but ultimately a different source.

– Nicol Bolas
Dec 16 '18 at 23:54





@NeilButterworth: "Any problems with these proposals?" Because the most-vexing parse is usually presented as a competition between creating a temporary and declaring a function. This is instead treated as creating a variable. Similar idea, similar resolution, but ultimately a different source.

– Nicol Bolas
Dec 16 '18 at 23:54




4




4





@Nicol "Any problems with these proposals?" - um, what? Where?

– Neil Butterworth
Dec 17 '18 at 0:12







@Nicol "Any problems with these proposals?" - um, what? Where?

– Neil Butterworth
Dec 17 '18 at 0:12






4




4





I upvoted the question and answers because I learned something new. I was aware of the most-vexing parse, and this manifestation of it was different enough from previous ones I've seen. The answers were helpful, and the workarounds were interesting.

– Eljay
Dec 17 '18 at 1:43





I upvoted the question and answers because I learned something new. I was aware of the most-vexing parse, and this manifestation of it was different enough from previous ones I've seen. The answers were helpful, and the workarounds were interesting.

– Eljay
Dec 17 '18 at 1:43




11




11





@user202729: But they aren't. Simply saying "most vexing parse" doesn't answer the question. You have to explain how it is a "most vexing parse". And that requires explaining that it's trying to declare a variable in this case, but a function in other cases. Those are different things, for different reasons, and thus have to be different answers.

– Nicol Bolas
Dec 17 '18 at 14:36







@user202729: But they aren't. Simply saying "most vexing parse" doesn't answer the question. You have to explain how it is a "most vexing parse". And that requires explaining that it's trying to declare a variable in this case, but a function in other cases. Those are different things, for different reasons, and thus have to be different answers.

– Nicol Bolas
Dec 17 '18 at 14:36














3 Answers
3






active

oldest

votes


















87














Clang gives this warning message:



<source>:12:16: warning: parentheses were disambiguated as redundant parentheses around declaration of variable named 'num' [-Wvexing-parse]
Boo(num); // No default constructor
^~~~~


This is a most-vexing parse issue. Because Boo is the name of a class type and num is not a type name, Boo(num); could be either the construction of a temporary of type Boo with num being argument to Boo's constructor or it could be a declaration Boo num; with extra parentheses around the declarator num (which declarators may always have). If both are valid interpretations, the standard requires the compiler to assume a declaration.



If it is parsed as declaration, then Boo num; would call the default constructor (the constructor without arguments), which isn't declared either by you or implicitly (because you declared a another constructor). Therefore the program is ill-formed.



This is not an issue with Boo(8);, because 8 cannot be a variable's identifier (declarator-id), so it is parsed as a call creating a Boo temporary with 8 as argument to the constructor, thereby not calling the default constructor (which is not declared), but the one you defined manually.



You can disambiguate this from a declaration by either using Boo{num}; instead of Boo(num); (because {} around the declarator is not allowed), by making the temporary a named variable, e.g. Boo temp(num);, or by putting it as an operand in another expression, e.g. (Boo(num));, (void)Boo(num);, etc.



Note that the declaration would be well-formed if the default constructor was usable, because it is inside the if's branch block scope rather than the function's block scope and would simply shadow the num in the function's parameter list.



In any case it doesn't seem a good idea to misuse temporary object creation for something that should be a normal (member) function call.



This particular type of most-vexing parse with a single non-type name in the parenthesis can only happen because the intend is to create a temporary and immediately discard it or alternatively if the intend is to create a temporary used directly as an initializer, e.g. Boo boo(Boo(num)); (actually declares function boo taking a parameter named num with type Boo and returning Boo).



Discarding temporaries immediately is usually not intended and the initializer case can be avoided using brace-initialization or double-parantheses (Boo boo{Boo(num)}, Boo boo(Boo{num}) or Boo boo((Boo(num)));, but not Boo boo(Boo((num)));).



If Boo wasn't a type name, it could not be a declaration and no problem occurs.



I also want to emphasize that Boo(8); is creating a new temporary of type Boo, even inside the class scope and constructor definition. It is not, as one might erroneously think, a call to the constructor with the caller's this pointer like for usual non-static member functions. It is not possible to call another constructor in this way inside the constructor body. This is only possible in the member initializer list of the constructor.





This happens even though the declaration would be ill-formed due to missing constructor, because of [stmt.ambig]/3:




The disambiguation is purely syntactic; that is, the meaning of the
names occurring in such a statement, beyond whether they are
type-names or not, is not generally used in or changed by the
disambiguation.



[...]



Disambiguation precedes parsing, and a statement disambiguated as a declaration may be an ill-formed declaration.






Fixed in edit: I overlooked the declaration in question being in a different scope than the function parameter and the declaration therefore being well-formed if the constructor was available. This is not considered during disambiguation in any case. Also expanded on some details.






share|improve this answer


























  • Thanks for your answer, that makes sense if it's a type of vexing parse problem. What I don't get is that num is a local variable, and don't see how this could be mistaken for a type, which is usually when the vexing parse problem comes up I think.

    – Zebrafish
    Dec 16 '18 at 22:29











  • @Zebrafish I added the paragraph of the standard which seems to be responsible. It is not mistaken for a type. It is used as a variable name and the only confusion seems to be that the name is already declared in the scope with different type.

    – user10605163
    Dec 16 '18 at 22:38













  • I see. So it seems it allows Boo(8) not so much because 8 is unambiguous with respect to an argument, but more because 8 can't be the name of an identifier for an object, if I understand right.

    – Zebrafish
    Dec 16 '18 at 22:46






  • 2





    Yes that is correct. The issue also does not exist if the temporary Boo(...) is used inside another expression, because then it cannot be a declaration statement. You are only seeing this weird case because you are creating unnamed temporaries and then immediately discarding them again. Simply don't do that.

    – user10605163
    Dec 16 '18 at 22:52








  • 1





    Been coding in C/C++ for so long and never would have guessed int(x)=5; is valid syntax... Vexing indeed.

    – Apollys
    Dec 17 '18 at 22:08



















33














This is known as the most vexing parse (The term was used by Scott Meyers in Effective STL).



Boo(num) does not invoke the constructor nor does it create a temporary. Clang gives a good warning to see (even with the right name Wvexing-parse):



<source>:12:38: warning: parentheses were disambiguated as redundant parentheses around declaration of variable named 'num' [-Wvexing-parse]


So what the compiler sees is equivalent to



Boo num;


which is a variable decleration. You declared a Boo variable with name num, which needs the default constructor, even though you wanted to create a temporary Boo-object. The c++ standard requires the compiler in your case to assume this is a variable declaration. You might now say: "Hey, num is an int, don't do that." However, the standard says:




The disambiguation is purely syntactic; that is, the meaning of the names occurring in such a statement, beyond whether they are type-names or not, is not generally used in or changed by the disambiguation.
Class templates are instantiated as necessary to determine if a qualified name is a type-name.
Disambiguation precedes parsing, and a statement disambiguated as a declaration may be an ill-formed declaration.
If, during parsing, a name in a template parameter is bound differently than it would be bound during a trial parse, the program is ill-formed.
No diagnostic is required.
[ Note: This can occur only when the name is declared earlier in the declaration.
— end note
 ]




So there is no way out of this.



For Boo(8) this cannot happen, as the parser can be sure this is not a decleration (8 is not a valid identifier name) and invokes the constructor Boo(int).



By the way: You can disambiguate by using enclosing parentheses:



 if (rand() % num < 7)  (Boo(num));


or in my opinion better, use the new uniform initialization syntax



if (rand() % num < 7)  Boo{num};


Which will then compile see here and here.






share|improve this answer





















  • 2





    You're quoting the wrong section and "requires the compiler in your rcase to assume this is a function declaration" is not true, since num is not a function but a variable.

    – Rakete1111
    Dec 17 '18 at 7:29






  • 1





    Thanks for spotting, will have to fix it later.

    – user32434999
    Dec 17 '18 at 7:34











  • There is no such thing as "a call to the constructor" in the manner you describe; the intent was an utterance of a functional-cast to create a temporary; the syntax to do this looks a bit like a "constructor call" but in fact no such thing is syntactically (or semantically) possible. There are a few scenarios in which a constructor is invoked but these are all triggered for you by the language when you do other things.

    – Lightness Races in Orbit
    Dec 17 '18 at 11:10













  • @LightnessRacesinOrbit Correct. Fixed it. Thanks for taking the time and help improving the answer.

    – user32434999
    Dec 17 '18 at 11:16













  • It's kind of embarrasing that Boo (num) compiles; probably should have been a syntax error with only Boo (num)() allowed.

    – Joshua
    Dec 17 '18 at 22:58



















1














Here is clang warning



truct_init.cpp:11:11: error: redefinition of 'num' with a different type: 'Boo'
vs 'int'






share|improve this answer























    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53806896%2fwhy-wont-this-compile-without-a-default-constructor%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    3 Answers
    3






    active

    oldest

    votes








    3 Answers
    3






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    87














    Clang gives this warning message:



    <source>:12:16: warning: parentheses were disambiguated as redundant parentheses around declaration of variable named 'num' [-Wvexing-parse]
    Boo(num); // No default constructor
    ^~~~~


    This is a most-vexing parse issue. Because Boo is the name of a class type and num is not a type name, Boo(num); could be either the construction of a temporary of type Boo with num being argument to Boo's constructor or it could be a declaration Boo num; with extra parentheses around the declarator num (which declarators may always have). If both are valid interpretations, the standard requires the compiler to assume a declaration.



    If it is parsed as declaration, then Boo num; would call the default constructor (the constructor without arguments), which isn't declared either by you or implicitly (because you declared a another constructor). Therefore the program is ill-formed.



    This is not an issue with Boo(8);, because 8 cannot be a variable's identifier (declarator-id), so it is parsed as a call creating a Boo temporary with 8 as argument to the constructor, thereby not calling the default constructor (which is not declared), but the one you defined manually.



    You can disambiguate this from a declaration by either using Boo{num}; instead of Boo(num); (because {} around the declarator is not allowed), by making the temporary a named variable, e.g. Boo temp(num);, or by putting it as an operand in another expression, e.g. (Boo(num));, (void)Boo(num);, etc.



    Note that the declaration would be well-formed if the default constructor was usable, because it is inside the if's branch block scope rather than the function's block scope and would simply shadow the num in the function's parameter list.



    In any case it doesn't seem a good idea to misuse temporary object creation for something that should be a normal (member) function call.



    This particular type of most-vexing parse with a single non-type name in the parenthesis can only happen because the intend is to create a temporary and immediately discard it or alternatively if the intend is to create a temporary used directly as an initializer, e.g. Boo boo(Boo(num)); (actually declares function boo taking a parameter named num with type Boo and returning Boo).



    Discarding temporaries immediately is usually not intended and the initializer case can be avoided using brace-initialization or double-parantheses (Boo boo{Boo(num)}, Boo boo(Boo{num}) or Boo boo((Boo(num)));, but not Boo boo(Boo((num)));).



    If Boo wasn't a type name, it could not be a declaration and no problem occurs.



    I also want to emphasize that Boo(8); is creating a new temporary of type Boo, even inside the class scope and constructor definition. It is not, as one might erroneously think, a call to the constructor with the caller's this pointer like for usual non-static member functions. It is not possible to call another constructor in this way inside the constructor body. This is only possible in the member initializer list of the constructor.





    This happens even though the declaration would be ill-formed due to missing constructor, because of [stmt.ambig]/3:




    The disambiguation is purely syntactic; that is, the meaning of the
    names occurring in such a statement, beyond whether they are
    type-names or not, is not generally used in or changed by the
    disambiguation.



    [...]



    Disambiguation precedes parsing, and a statement disambiguated as a declaration may be an ill-formed declaration.






    Fixed in edit: I overlooked the declaration in question being in a different scope than the function parameter and the declaration therefore being well-formed if the constructor was available. This is not considered during disambiguation in any case. Also expanded on some details.






    share|improve this answer


























    • Thanks for your answer, that makes sense if it's a type of vexing parse problem. What I don't get is that num is a local variable, and don't see how this could be mistaken for a type, which is usually when the vexing parse problem comes up I think.

      – Zebrafish
      Dec 16 '18 at 22:29











    • @Zebrafish I added the paragraph of the standard which seems to be responsible. It is not mistaken for a type. It is used as a variable name and the only confusion seems to be that the name is already declared in the scope with different type.

      – user10605163
      Dec 16 '18 at 22:38













    • I see. So it seems it allows Boo(8) not so much because 8 is unambiguous with respect to an argument, but more because 8 can't be the name of an identifier for an object, if I understand right.

      – Zebrafish
      Dec 16 '18 at 22:46






    • 2





      Yes that is correct. The issue also does not exist if the temporary Boo(...) is used inside another expression, because then it cannot be a declaration statement. You are only seeing this weird case because you are creating unnamed temporaries and then immediately discarding them again. Simply don't do that.

      – user10605163
      Dec 16 '18 at 22:52








    • 1





      Been coding in C/C++ for so long and never would have guessed int(x)=5; is valid syntax... Vexing indeed.

      – Apollys
      Dec 17 '18 at 22:08
















    87














    Clang gives this warning message:



    <source>:12:16: warning: parentheses were disambiguated as redundant parentheses around declaration of variable named 'num' [-Wvexing-parse]
    Boo(num); // No default constructor
    ^~~~~


    This is a most-vexing parse issue. Because Boo is the name of a class type and num is not a type name, Boo(num); could be either the construction of a temporary of type Boo with num being argument to Boo's constructor or it could be a declaration Boo num; with extra parentheses around the declarator num (which declarators may always have). If both are valid interpretations, the standard requires the compiler to assume a declaration.



    If it is parsed as declaration, then Boo num; would call the default constructor (the constructor without arguments), which isn't declared either by you or implicitly (because you declared a another constructor). Therefore the program is ill-formed.



    This is not an issue with Boo(8);, because 8 cannot be a variable's identifier (declarator-id), so it is parsed as a call creating a Boo temporary with 8 as argument to the constructor, thereby not calling the default constructor (which is not declared), but the one you defined manually.



    You can disambiguate this from a declaration by either using Boo{num}; instead of Boo(num); (because {} around the declarator is not allowed), by making the temporary a named variable, e.g. Boo temp(num);, or by putting it as an operand in another expression, e.g. (Boo(num));, (void)Boo(num);, etc.



    Note that the declaration would be well-formed if the default constructor was usable, because it is inside the if's branch block scope rather than the function's block scope and would simply shadow the num in the function's parameter list.



    In any case it doesn't seem a good idea to misuse temporary object creation for something that should be a normal (member) function call.



    This particular type of most-vexing parse with a single non-type name in the parenthesis can only happen because the intend is to create a temporary and immediately discard it or alternatively if the intend is to create a temporary used directly as an initializer, e.g. Boo boo(Boo(num)); (actually declares function boo taking a parameter named num with type Boo and returning Boo).



    Discarding temporaries immediately is usually not intended and the initializer case can be avoided using brace-initialization or double-parantheses (Boo boo{Boo(num)}, Boo boo(Boo{num}) or Boo boo((Boo(num)));, but not Boo boo(Boo((num)));).



    If Boo wasn't a type name, it could not be a declaration and no problem occurs.



    I also want to emphasize that Boo(8); is creating a new temporary of type Boo, even inside the class scope and constructor definition. It is not, as one might erroneously think, a call to the constructor with the caller's this pointer like for usual non-static member functions. It is not possible to call another constructor in this way inside the constructor body. This is only possible in the member initializer list of the constructor.





    This happens even though the declaration would be ill-formed due to missing constructor, because of [stmt.ambig]/3:




    The disambiguation is purely syntactic; that is, the meaning of the
    names occurring in such a statement, beyond whether they are
    type-names or not, is not generally used in or changed by the
    disambiguation.



    [...]



    Disambiguation precedes parsing, and a statement disambiguated as a declaration may be an ill-formed declaration.






    Fixed in edit: I overlooked the declaration in question being in a different scope than the function parameter and the declaration therefore being well-formed if the constructor was available. This is not considered during disambiguation in any case. Also expanded on some details.






    share|improve this answer


























    • Thanks for your answer, that makes sense if it's a type of vexing parse problem. What I don't get is that num is a local variable, and don't see how this could be mistaken for a type, which is usually when the vexing parse problem comes up I think.

      – Zebrafish
      Dec 16 '18 at 22:29











    • @Zebrafish I added the paragraph of the standard which seems to be responsible. It is not mistaken for a type. It is used as a variable name and the only confusion seems to be that the name is already declared in the scope with different type.

      – user10605163
      Dec 16 '18 at 22:38













    • I see. So it seems it allows Boo(8) not so much because 8 is unambiguous with respect to an argument, but more because 8 can't be the name of an identifier for an object, if I understand right.

      – Zebrafish
      Dec 16 '18 at 22:46






    • 2





      Yes that is correct. The issue also does not exist if the temporary Boo(...) is used inside another expression, because then it cannot be a declaration statement. You are only seeing this weird case because you are creating unnamed temporaries and then immediately discarding them again. Simply don't do that.

      – user10605163
      Dec 16 '18 at 22:52








    • 1





      Been coding in C/C++ for so long and never would have guessed int(x)=5; is valid syntax... Vexing indeed.

      – Apollys
      Dec 17 '18 at 22:08














    87












    87








    87







    Clang gives this warning message:



    <source>:12:16: warning: parentheses were disambiguated as redundant parentheses around declaration of variable named 'num' [-Wvexing-parse]
    Boo(num); // No default constructor
    ^~~~~


    This is a most-vexing parse issue. Because Boo is the name of a class type and num is not a type name, Boo(num); could be either the construction of a temporary of type Boo with num being argument to Boo's constructor or it could be a declaration Boo num; with extra parentheses around the declarator num (which declarators may always have). If both are valid interpretations, the standard requires the compiler to assume a declaration.



    If it is parsed as declaration, then Boo num; would call the default constructor (the constructor without arguments), which isn't declared either by you or implicitly (because you declared a another constructor). Therefore the program is ill-formed.



    This is not an issue with Boo(8);, because 8 cannot be a variable's identifier (declarator-id), so it is parsed as a call creating a Boo temporary with 8 as argument to the constructor, thereby not calling the default constructor (which is not declared), but the one you defined manually.



    You can disambiguate this from a declaration by either using Boo{num}; instead of Boo(num); (because {} around the declarator is not allowed), by making the temporary a named variable, e.g. Boo temp(num);, or by putting it as an operand in another expression, e.g. (Boo(num));, (void)Boo(num);, etc.



    Note that the declaration would be well-formed if the default constructor was usable, because it is inside the if's branch block scope rather than the function's block scope and would simply shadow the num in the function's parameter list.



    In any case it doesn't seem a good idea to misuse temporary object creation for something that should be a normal (member) function call.



    This particular type of most-vexing parse with a single non-type name in the parenthesis can only happen because the intend is to create a temporary and immediately discard it or alternatively if the intend is to create a temporary used directly as an initializer, e.g. Boo boo(Boo(num)); (actually declares function boo taking a parameter named num with type Boo and returning Boo).



    Discarding temporaries immediately is usually not intended and the initializer case can be avoided using brace-initialization or double-parantheses (Boo boo{Boo(num)}, Boo boo(Boo{num}) or Boo boo((Boo(num)));, but not Boo boo(Boo((num)));).



    If Boo wasn't a type name, it could not be a declaration and no problem occurs.



    I also want to emphasize that Boo(8); is creating a new temporary of type Boo, even inside the class scope and constructor definition. It is not, as one might erroneously think, a call to the constructor with the caller's this pointer like for usual non-static member functions. It is not possible to call another constructor in this way inside the constructor body. This is only possible in the member initializer list of the constructor.





    This happens even though the declaration would be ill-formed due to missing constructor, because of [stmt.ambig]/3:




    The disambiguation is purely syntactic; that is, the meaning of the
    names occurring in such a statement, beyond whether they are
    type-names or not, is not generally used in or changed by the
    disambiguation.



    [...]



    Disambiguation precedes parsing, and a statement disambiguated as a declaration may be an ill-formed declaration.






    Fixed in edit: I overlooked the declaration in question being in a different scope than the function parameter and the declaration therefore being well-formed if the constructor was available. This is not considered during disambiguation in any case. Also expanded on some details.






    share|improve this answer















    Clang gives this warning message:



    <source>:12:16: warning: parentheses were disambiguated as redundant parentheses around declaration of variable named 'num' [-Wvexing-parse]
    Boo(num); // No default constructor
    ^~~~~


    This is a most-vexing parse issue. Because Boo is the name of a class type and num is not a type name, Boo(num); could be either the construction of a temporary of type Boo with num being argument to Boo's constructor or it could be a declaration Boo num; with extra parentheses around the declarator num (which declarators may always have). If both are valid interpretations, the standard requires the compiler to assume a declaration.



    If it is parsed as declaration, then Boo num; would call the default constructor (the constructor without arguments), which isn't declared either by you or implicitly (because you declared a another constructor). Therefore the program is ill-formed.



    This is not an issue with Boo(8);, because 8 cannot be a variable's identifier (declarator-id), so it is parsed as a call creating a Boo temporary with 8 as argument to the constructor, thereby not calling the default constructor (which is not declared), but the one you defined manually.



    You can disambiguate this from a declaration by either using Boo{num}; instead of Boo(num); (because {} around the declarator is not allowed), by making the temporary a named variable, e.g. Boo temp(num);, or by putting it as an operand in another expression, e.g. (Boo(num));, (void)Boo(num);, etc.



    Note that the declaration would be well-formed if the default constructor was usable, because it is inside the if's branch block scope rather than the function's block scope and would simply shadow the num in the function's parameter list.



    In any case it doesn't seem a good idea to misuse temporary object creation for something that should be a normal (member) function call.



    This particular type of most-vexing parse with a single non-type name in the parenthesis can only happen because the intend is to create a temporary and immediately discard it or alternatively if the intend is to create a temporary used directly as an initializer, e.g. Boo boo(Boo(num)); (actually declares function boo taking a parameter named num with type Boo and returning Boo).



    Discarding temporaries immediately is usually not intended and the initializer case can be avoided using brace-initialization or double-parantheses (Boo boo{Boo(num)}, Boo boo(Boo{num}) or Boo boo((Boo(num)));, but not Boo boo(Boo((num)));).



    If Boo wasn't a type name, it could not be a declaration and no problem occurs.



    I also want to emphasize that Boo(8); is creating a new temporary of type Boo, even inside the class scope and constructor definition. It is not, as one might erroneously think, a call to the constructor with the caller's this pointer like for usual non-static member functions. It is not possible to call another constructor in this way inside the constructor body. This is only possible in the member initializer list of the constructor.





    This happens even though the declaration would be ill-formed due to missing constructor, because of [stmt.ambig]/3:




    The disambiguation is purely syntactic; that is, the meaning of the
    names occurring in such a statement, beyond whether they are
    type-names or not, is not generally used in or changed by the
    disambiguation.



    [...]



    Disambiguation precedes parsing, and a statement disambiguated as a declaration may be an ill-formed declaration.






    Fixed in edit: I overlooked the declaration in question being in a different scope than the function parameter and the declaration therefore being well-formed if the constructor was available. This is not considered during disambiguation in any case. Also expanded on some details.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Dec 18 '18 at 23:49

























    answered Dec 16 '18 at 22:21









    user10605163user10605163

    2,868624




    2,868624













    • Thanks for your answer, that makes sense if it's a type of vexing parse problem. What I don't get is that num is a local variable, and don't see how this could be mistaken for a type, which is usually when the vexing parse problem comes up I think.

      – Zebrafish
      Dec 16 '18 at 22:29











    • @Zebrafish I added the paragraph of the standard which seems to be responsible. It is not mistaken for a type. It is used as a variable name and the only confusion seems to be that the name is already declared in the scope with different type.

      – user10605163
      Dec 16 '18 at 22:38













    • I see. So it seems it allows Boo(8) not so much because 8 is unambiguous with respect to an argument, but more because 8 can't be the name of an identifier for an object, if I understand right.

      – Zebrafish
      Dec 16 '18 at 22:46






    • 2





      Yes that is correct. The issue also does not exist if the temporary Boo(...) is used inside another expression, because then it cannot be a declaration statement. You are only seeing this weird case because you are creating unnamed temporaries and then immediately discarding them again. Simply don't do that.

      – user10605163
      Dec 16 '18 at 22:52








    • 1





      Been coding in C/C++ for so long and never would have guessed int(x)=5; is valid syntax... Vexing indeed.

      – Apollys
      Dec 17 '18 at 22:08



















    • Thanks for your answer, that makes sense if it's a type of vexing parse problem. What I don't get is that num is a local variable, and don't see how this could be mistaken for a type, which is usually when the vexing parse problem comes up I think.

      – Zebrafish
      Dec 16 '18 at 22:29











    • @Zebrafish I added the paragraph of the standard which seems to be responsible. It is not mistaken for a type. It is used as a variable name and the only confusion seems to be that the name is already declared in the scope with different type.

      – user10605163
      Dec 16 '18 at 22:38













    • I see. So it seems it allows Boo(8) not so much because 8 is unambiguous with respect to an argument, but more because 8 can't be the name of an identifier for an object, if I understand right.

      – Zebrafish
      Dec 16 '18 at 22:46






    • 2





      Yes that is correct. The issue also does not exist if the temporary Boo(...) is used inside another expression, because then it cannot be a declaration statement. You are only seeing this weird case because you are creating unnamed temporaries and then immediately discarding them again. Simply don't do that.

      – user10605163
      Dec 16 '18 at 22:52








    • 1





      Been coding in C/C++ for so long and never would have guessed int(x)=5; is valid syntax... Vexing indeed.

      – Apollys
      Dec 17 '18 at 22:08

















    Thanks for your answer, that makes sense if it's a type of vexing parse problem. What I don't get is that num is a local variable, and don't see how this could be mistaken for a type, which is usually when the vexing parse problem comes up I think.

    – Zebrafish
    Dec 16 '18 at 22:29





    Thanks for your answer, that makes sense if it's a type of vexing parse problem. What I don't get is that num is a local variable, and don't see how this could be mistaken for a type, which is usually when the vexing parse problem comes up I think.

    – Zebrafish
    Dec 16 '18 at 22:29













    @Zebrafish I added the paragraph of the standard which seems to be responsible. It is not mistaken for a type. It is used as a variable name and the only confusion seems to be that the name is already declared in the scope with different type.

    – user10605163
    Dec 16 '18 at 22:38







    @Zebrafish I added the paragraph of the standard which seems to be responsible. It is not mistaken for a type. It is used as a variable name and the only confusion seems to be that the name is already declared in the scope with different type.

    – user10605163
    Dec 16 '18 at 22:38















    I see. So it seems it allows Boo(8) not so much because 8 is unambiguous with respect to an argument, but more because 8 can't be the name of an identifier for an object, if I understand right.

    – Zebrafish
    Dec 16 '18 at 22:46





    I see. So it seems it allows Boo(8) not so much because 8 is unambiguous with respect to an argument, but more because 8 can't be the name of an identifier for an object, if I understand right.

    – Zebrafish
    Dec 16 '18 at 22:46




    2




    2





    Yes that is correct. The issue also does not exist if the temporary Boo(...) is used inside another expression, because then it cannot be a declaration statement. You are only seeing this weird case because you are creating unnamed temporaries and then immediately discarding them again. Simply don't do that.

    – user10605163
    Dec 16 '18 at 22:52







    Yes that is correct. The issue also does not exist if the temporary Boo(...) is used inside another expression, because then it cannot be a declaration statement. You are only seeing this weird case because you are creating unnamed temporaries and then immediately discarding them again. Simply don't do that.

    – user10605163
    Dec 16 '18 at 22:52






    1




    1





    Been coding in C/C++ for so long and never would have guessed int(x)=5; is valid syntax... Vexing indeed.

    – Apollys
    Dec 17 '18 at 22:08





    Been coding in C/C++ for so long and never would have guessed int(x)=5; is valid syntax... Vexing indeed.

    – Apollys
    Dec 17 '18 at 22:08













    33














    This is known as the most vexing parse (The term was used by Scott Meyers in Effective STL).



    Boo(num) does not invoke the constructor nor does it create a temporary. Clang gives a good warning to see (even with the right name Wvexing-parse):



    <source>:12:38: warning: parentheses were disambiguated as redundant parentheses around declaration of variable named 'num' [-Wvexing-parse]


    So what the compiler sees is equivalent to



    Boo num;


    which is a variable decleration. You declared a Boo variable with name num, which needs the default constructor, even though you wanted to create a temporary Boo-object. The c++ standard requires the compiler in your case to assume this is a variable declaration. You might now say: "Hey, num is an int, don't do that." However, the standard says:




    The disambiguation is purely syntactic; that is, the meaning of the names occurring in such a statement, beyond whether they are type-names or not, is not generally used in or changed by the disambiguation.
    Class templates are instantiated as necessary to determine if a qualified name is a type-name.
    Disambiguation precedes parsing, and a statement disambiguated as a declaration may be an ill-formed declaration.
    If, during parsing, a name in a template parameter is bound differently than it would be bound during a trial parse, the program is ill-formed.
    No diagnostic is required.
    [ Note: This can occur only when the name is declared earlier in the declaration.
    — end note
     ]




    So there is no way out of this.



    For Boo(8) this cannot happen, as the parser can be sure this is not a decleration (8 is not a valid identifier name) and invokes the constructor Boo(int).



    By the way: You can disambiguate by using enclosing parentheses:



     if (rand() % num < 7)  (Boo(num));


    or in my opinion better, use the new uniform initialization syntax



    if (rand() % num < 7)  Boo{num};


    Which will then compile see here and here.






    share|improve this answer





















    • 2





      You're quoting the wrong section and "requires the compiler in your rcase to assume this is a function declaration" is not true, since num is not a function but a variable.

      – Rakete1111
      Dec 17 '18 at 7:29






    • 1





      Thanks for spotting, will have to fix it later.

      – user32434999
      Dec 17 '18 at 7:34











    • There is no such thing as "a call to the constructor" in the manner you describe; the intent was an utterance of a functional-cast to create a temporary; the syntax to do this looks a bit like a "constructor call" but in fact no such thing is syntactically (or semantically) possible. There are a few scenarios in which a constructor is invoked but these are all triggered for you by the language when you do other things.

      – Lightness Races in Orbit
      Dec 17 '18 at 11:10













    • @LightnessRacesinOrbit Correct. Fixed it. Thanks for taking the time and help improving the answer.

      – user32434999
      Dec 17 '18 at 11:16













    • It's kind of embarrasing that Boo (num) compiles; probably should have been a syntax error with only Boo (num)() allowed.

      – Joshua
      Dec 17 '18 at 22:58
















    33














    This is known as the most vexing parse (The term was used by Scott Meyers in Effective STL).



    Boo(num) does not invoke the constructor nor does it create a temporary. Clang gives a good warning to see (even with the right name Wvexing-parse):



    <source>:12:38: warning: parentheses were disambiguated as redundant parentheses around declaration of variable named 'num' [-Wvexing-parse]


    So what the compiler sees is equivalent to



    Boo num;


    which is a variable decleration. You declared a Boo variable with name num, which needs the default constructor, even though you wanted to create a temporary Boo-object. The c++ standard requires the compiler in your case to assume this is a variable declaration. You might now say: "Hey, num is an int, don't do that." However, the standard says:




    The disambiguation is purely syntactic; that is, the meaning of the names occurring in such a statement, beyond whether they are type-names or not, is not generally used in or changed by the disambiguation.
    Class templates are instantiated as necessary to determine if a qualified name is a type-name.
    Disambiguation precedes parsing, and a statement disambiguated as a declaration may be an ill-formed declaration.
    If, during parsing, a name in a template parameter is bound differently than it would be bound during a trial parse, the program is ill-formed.
    No diagnostic is required.
    [ Note: This can occur only when the name is declared earlier in the declaration.
    — end note
     ]




    So there is no way out of this.



    For Boo(8) this cannot happen, as the parser can be sure this is not a decleration (8 is not a valid identifier name) and invokes the constructor Boo(int).



    By the way: You can disambiguate by using enclosing parentheses:



     if (rand() % num < 7)  (Boo(num));


    or in my opinion better, use the new uniform initialization syntax



    if (rand() % num < 7)  Boo{num};


    Which will then compile see here and here.






    share|improve this answer





















    • 2





      You're quoting the wrong section and "requires the compiler in your rcase to assume this is a function declaration" is not true, since num is not a function but a variable.

      – Rakete1111
      Dec 17 '18 at 7:29






    • 1





      Thanks for spotting, will have to fix it later.

      – user32434999
      Dec 17 '18 at 7:34











    • There is no such thing as "a call to the constructor" in the manner you describe; the intent was an utterance of a functional-cast to create a temporary; the syntax to do this looks a bit like a "constructor call" but in fact no such thing is syntactically (or semantically) possible. There are a few scenarios in which a constructor is invoked but these are all triggered for you by the language when you do other things.

      – Lightness Races in Orbit
      Dec 17 '18 at 11:10













    • @LightnessRacesinOrbit Correct. Fixed it. Thanks for taking the time and help improving the answer.

      – user32434999
      Dec 17 '18 at 11:16













    • It's kind of embarrasing that Boo (num) compiles; probably should have been a syntax error with only Boo (num)() allowed.

      – Joshua
      Dec 17 '18 at 22:58














    33












    33








    33







    This is known as the most vexing parse (The term was used by Scott Meyers in Effective STL).



    Boo(num) does not invoke the constructor nor does it create a temporary. Clang gives a good warning to see (even with the right name Wvexing-parse):



    <source>:12:38: warning: parentheses were disambiguated as redundant parentheses around declaration of variable named 'num' [-Wvexing-parse]


    So what the compiler sees is equivalent to



    Boo num;


    which is a variable decleration. You declared a Boo variable with name num, which needs the default constructor, even though you wanted to create a temporary Boo-object. The c++ standard requires the compiler in your case to assume this is a variable declaration. You might now say: "Hey, num is an int, don't do that." However, the standard says:




    The disambiguation is purely syntactic; that is, the meaning of the names occurring in such a statement, beyond whether they are type-names or not, is not generally used in or changed by the disambiguation.
    Class templates are instantiated as necessary to determine if a qualified name is a type-name.
    Disambiguation precedes parsing, and a statement disambiguated as a declaration may be an ill-formed declaration.
    If, during parsing, a name in a template parameter is bound differently than it would be bound during a trial parse, the program is ill-formed.
    No diagnostic is required.
    [ Note: This can occur only when the name is declared earlier in the declaration.
    — end note
     ]




    So there is no way out of this.



    For Boo(8) this cannot happen, as the parser can be sure this is not a decleration (8 is not a valid identifier name) and invokes the constructor Boo(int).



    By the way: You can disambiguate by using enclosing parentheses:



     if (rand() % num < 7)  (Boo(num));


    or in my opinion better, use the new uniform initialization syntax



    if (rand() % num < 7)  Boo{num};


    Which will then compile see here and here.






    share|improve this answer















    This is known as the most vexing parse (The term was used by Scott Meyers in Effective STL).



    Boo(num) does not invoke the constructor nor does it create a temporary. Clang gives a good warning to see (even with the right name Wvexing-parse):



    <source>:12:38: warning: parentheses were disambiguated as redundant parentheses around declaration of variable named 'num' [-Wvexing-parse]


    So what the compiler sees is equivalent to



    Boo num;


    which is a variable decleration. You declared a Boo variable with name num, which needs the default constructor, even though you wanted to create a temporary Boo-object. The c++ standard requires the compiler in your case to assume this is a variable declaration. You might now say: "Hey, num is an int, don't do that." However, the standard says:




    The disambiguation is purely syntactic; that is, the meaning of the names occurring in such a statement, beyond whether they are type-names or not, is not generally used in or changed by the disambiguation.
    Class templates are instantiated as necessary to determine if a qualified name is a type-name.
    Disambiguation precedes parsing, and a statement disambiguated as a declaration may be an ill-formed declaration.
    If, during parsing, a name in a template parameter is bound differently than it would be bound during a trial parse, the program is ill-formed.
    No diagnostic is required.
    [ Note: This can occur only when the name is declared earlier in the declaration.
    — end note
     ]




    So there is no way out of this.



    For Boo(8) this cannot happen, as the parser can be sure this is not a decleration (8 is not a valid identifier name) and invokes the constructor Boo(int).



    By the way: You can disambiguate by using enclosing parentheses:



     if (rand() % num < 7)  (Boo(num));


    or in my opinion better, use the new uniform initialization syntax



    if (rand() % num < 7)  Boo{num};


    Which will then compile see here and here.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Dec 18 '18 at 21:00

























    answered Dec 16 '18 at 22:21









    user32434999user32434999

    3,1741234




    3,1741234








    • 2





      You're quoting the wrong section and "requires the compiler in your rcase to assume this is a function declaration" is not true, since num is not a function but a variable.

      – Rakete1111
      Dec 17 '18 at 7:29






    • 1





      Thanks for spotting, will have to fix it later.

      – user32434999
      Dec 17 '18 at 7:34











    • There is no such thing as "a call to the constructor" in the manner you describe; the intent was an utterance of a functional-cast to create a temporary; the syntax to do this looks a bit like a "constructor call" but in fact no such thing is syntactically (or semantically) possible. There are a few scenarios in which a constructor is invoked but these are all triggered for you by the language when you do other things.

      – Lightness Races in Orbit
      Dec 17 '18 at 11:10













    • @LightnessRacesinOrbit Correct. Fixed it. Thanks for taking the time and help improving the answer.

      – user32434999
      Dec 17 '18 at 11:16













    • It's kind of embarrasing that Boo (num) compiles; probably should have been a syntax error with only Boo (num)() allowed.

      – Joshua
      Dec 17 '18 at 22:58














    • 2





      You're quoting the wrong section and "requires the compiler in your rcase to assume this is a function declaration" is not true, since num is not a function but a variable.

      – Rakete1111
      Dec 17 '18 at 7:29






    • 1





      Thanks for spotting, will have to fix it later.

      – user32434999
      Dec 17 '18 at 7:34











    • There is no such thing as "a call to the constructor" in the manner you describe; the intent was an utterance of a functional-cast to create a temporary; the syntax to do this looks a bit like a "constructor call" but in fact no such thing is syntactically (or semantically) possible. There are a few scenarios in which a constructor is invoked but these are all triggered for you by the language when you do other things.

      – Lightness Races in Orbit
      Dec 17 '18 at 11:10













    • @LightnessRacesinOrbit Correct. Fixed it. Thanks for taking the time and help improving the answer.

      – user32434999
      Dec 17 '18 at 11:16













    • It's kind of embarrasing that Boo (num) compiles; probably should have been a syntax error with only Boo (num)() allowed.

      – Joshua
      Dec 17 '18 at 22:58








    2




    2





    You're quoting the wrong section and "requires the compiler in your rcase to assume this is a function declaration" is not true, since num is not a function but a variable.

    – Rakete1111
    Dec 17 '18 at 7:29





    You're quoting the wrong section and "requires the compiler in your rcase to assume this is a function declaration" is not true, since num is not a function but a variable.

    – Rakete1111
    Dec 17 '18 at 7:29




    1




    1





    Thanks for spotting, will have to fix it later.

    – user32434999
    Dec 17 '18 at 7:34





    Thanks for spotting, will have to fix it later.

    – user32434999
    Dec 17 '18 at 7:34













    There is no such thing as "a call to the constructor" in the manner you describe; the intent was an utterance of a functional-cast to create a temporary; the syntax to do this looks a bit like a "constructor call" but in fact no such thing is syntactically (or semantically) possible. There are a few scenarios in which a constructor is invoked but these are all triggered for you by the language when you do other things.

    – Lightness Races in Orbit
    Dec 17 '18 at 11:10







    There is no such thing as "a call to the constructor" in the manner you describe; the intent was an utterance of a functional-cast to create a temporary; the syntax to do this looks a bit like a "constructor call" but in fact no such thing is syntactically (or semantically) possible. There are a few scenarios in which a constructor is invoked but these are all triggered for you by the language when you do other things.

    – Lightness Races in Orbit
    Dec 17 '18 at 11:10















    @LightnessRacesinOrbit Correct. Fixed it. Thanks for taking the time and help improving the answer.

    – user32434999
    Dec 17 '18 at 11:16







    @LightnessRacesinOrbit Correct. Fixed it. Thanks for taking the time and help improving the answer.

    – user32434999
    Dec 17 '18 at 11:16















    It's kind of embarrasing that Boo (num) compiles; probably should have been a syntax error with only Boo (num)() allowed.

    – Joshua
    Dec 17 '18 at 22:58





    It's kind of embarrasing that Boo (num) compiles; probably should have been a syntax error with only Boo (num)() allowed.

    – Joshua
    Dec 17 '18 at 22:58











    1














    Here is clang warning



    truct_init.cpp:11:11: error: redefinition of 'num' with a different type: 'Boo'
    vs 'int'






    share|improve this answer




























      1














      Here is clang warning



      truct_init.cpp:11:11: error: redefinition of 'num' with a different type: 'Boo'
      vs 'int'






      share|improve this answer


























        1












        1








        1







        Here is clang warning



        truct_init.cpp:11:11: error: redefinition of 'num' with a different type: 'Boo'
        vs 'int'






        share|improve this answer













        Here is clang warning



        truct_init.cpp:11:11: error: redefinition of 'num' with a different type: 'Boo'
        vs 'int'







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Jan 5 at 20:09









        sbhsbh

        416




        416






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53806896%2fwhy-wont-this-compile-without-a-default-constructor%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Bundesstraße 106

            Verónica Boquete

            Ida-Boy-Ed-Garten