Why can member variables not be used as defaults for parameters? [duplicate] - c++

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Nonstatic member as a default argument of a nonstatic member function
Correct me if I am wrong, but the way I think default parameters work is this:
When the compiler sees the function call, it starts pushing the parameters onto the stack. When it runs out of parameters, it will start pushing the defaults onto the stack until all required parameters are filled (I know this is a simplification, since parameters are actually pushed from right to left, so it will start with the defaults, but the idea is the same).
If this is true, why can't member variables be used as defaults? It seems to me that since the compiler is pushing them as usual at the call site, it should be able to resolve them just fine!
EDIT Since it seems by the answers my question was misunderstood, let me clarify. I know this is the case, and I know what is and isn't allowed by the language. My question is why did the language designers choose to not allow this, since it seems to naturally work.

The essence of what you are asking can be distilled into this simple example
void foo(int a, int b = a);
This is not allowed in C++. C++ does not allow default arguments to depend on other parameters.
Using class members as default arguments is just a particular case of the above, since class members are accessed through this pointer and this pointer is just another hidden parameter of each non-static member function.
So, the question is really why
void foo(int a, int b = a);
is not allowed.
One obvious potential reason to disallow this is that it would impose additional requirements on the order of argument evaluation. As you know, in C++ the order of function argument evaluation is unspecified - the compiler can evaluate arguments in any order. However, in order to support the above default argument functionality the compiler would have to make sure that a is evaluated before b. This feels like an excessive requirement, which restricts the typical freedom of evaluation order that we are used to seeing in C++.
Note that this
int a;
void foo(int b = a);
is allowed in C++. And, obviously, it does not exhibit the aforementioned order of evaluation issue.

I believe this are the most fitting paragraphs from the standard, especially §9:
8.3.6 Default arguments [dcl.fct.default]
§7 Local variables shall not be used in a default argument
§9 [...] Similarly, a non-static member shall not be used in a default argument, even if it is not evaluated, unless it appears as the id-expression of a class member access expression (5.2.5) or unless it is used to form a pointer to member (5.3.1).

This post lists all ways a default param can be set - Must default function parameters be constant in C++?
It's not difficult to workaround your need.
class A
{
int a;
public:
void f(int i);
void f()
{
f(a);
}
};
gives you what you want.

Summarizing Nawaz excellent answer in the linked question: The call to void Foo::Bar(int a = this->member) really means void Foo__Bar(Foo* this, int a = this->member). Obviously the second argument cannot be evaluated before the first, which violates a C++ axiom that compilers can evaluate arguments in whatever order they like.

Related

calling a function inside header file [duplicate]

I have couple questions regarding some C++ rules.
Why am I able to call a function/method from outside the class in the namespace when I include the return type? (look at the namespace test2::testclass2 in the code below) i.e. this works:
bool b = testclass1::foo<int>(2);
whereas this doesn't: - (it doesn't even compile - compiler throws that this is function redeclaration)
testclass1::foo<int>(2);
C++ complains that it is a function redeclaration. Is that so?
This line:
bool b = testclass1::foo<int>(2);
gets called first before anything else. Is this because static methods get created always first before anything else in C++?
Where can I find those rules? I have a few C++ books at home, so if someone would be kind enough to either point out a book (and chapter or page) or direct me to a website I would greatly appreciate it.
Here below is the sample (partial) code that I tested at home with Visual Studio 2008:
class testclass1
{
public:
testclass1(void);
~testclass1(void);
template<class A> static bool foo(int i)
{
std::cout <<"in static foo";
return true;
}
};
namespace test2
{
class testclass2
{
public:
testclass2(void);
~testclass2(void);
};
bool b = testclass1::foo<int>(2);
}
EDIT:
A few people mentioned that I need to call this inside the function and this will work without any problem.
I understand that; the only reason I asked this question is because I saw this code somewhere (in someone's elses project) and was wondering how and why this works. Since I never really seen anyone doing it before.
Also, this is used (in multiple places) as a way to call and instantiate a large number of classes like this via those function calls (that are outside). They get called first before anything else is instantiated.
C++ is not Python. You write statements in functions and execution starts from the main method. The reason bool b = ... happens to work is that it's defining the global variable b and the function call is merely the initialization expression.
Definitions can exist outside functions while other statements can only exist inside a function body.
Why am I able to call a function/method from outside the class in the namespace when I include the return type? (look at the namespace test2::testclass2)
Your declaration of b is not inside a function, so you are declaring a global variable. If you were inside a function's scope, your second statement would work, but outside a function it makes no sense.
This also answers your second question.
Of course, you wouldn't be allowed to call it this way (i.e. not as a method of an object) if it weren't a static member function.
You can find the rules on e.g. Koenig lookup and template in the standard documentation -- good luck with navigating that! You're not mentioning which compiler you are testing, but I'm not entirely sure it's compliant!
As Mehrdad points out, you're declaring and initializing a global variable within the test2 namespace: this has nothing to do with static methods.
if you write this inside a function like below then it works without a problem. As mentioned above, you need to call these functions from within a function unless you are using the function to initialize a global variable ...
int main()
{
testclass1::foo<int>(2);
return 0;
}
1. First, a helpful correction: you said "...when I include the return type". I think you might be misunderstanding what the <int> part of testclass1::foo<int>(2) does. It doesn't (necessarily) specify the return type, it just provides a value for the template argument "A".
You could have chosen to use A as the return type, but you have the return type hard-coded to "bool".
Basically, for the function as you have written it you will always need to have the <> on it in order to call it. C++ does allow you to omit the <args> off the function when the type can be deduced from the function arguments; in order to get it to do that you have to use the type argument A in your function arguments. For instance if you declared the function this way instead then you could call it without the <>:
template<class A> static bool foo(A i);
In which case it you could call "foo(2)" and it would deduce A to be "int" from the number two.
On the other hand there isn't any way to make it deduce anything based on what you assign the function to. For template argument deduction it only looks at the arguments to the function, not what is done with the result of calling the function. So in:
bool b = testclass1::foo(2);
There is no way to get it to deduce "bool" from that, not even if you made A the return type.
So why doesn't the compiler just tell you "you needed to use <> on the function"? Even though you declared foo once as a template function, you could have also overloaded it with a non-template version too. So the compiler doesn't just automatically assume that you're trying to call a template function when you leave the <> off the call. Unfortunately having NOT assumed you were calling template-foo and not seeing any other declaration for foo, the compiler then falls back on an old C style rule where for a function that takes an int and returns an int, in a very old dialect of C you didn't need to declare that kind of before using it. So the compiler assumed THAT was what you wanted - but then it notices that template-foo and old-crufty-C-foo both take an int parameter, and realizes it wouldn't be able to tell the difference between them. So then it says you can't declare foo. This is why C++ compilers are notorious for giving bad error messages - by the time the error is reported the compiler may have gone completely off the rails and be talking about something that is three or four levels removed from your actual code!
2. Yes you're exactly right.
3. I find that the C++ references and whitepapers that IBM makes available online are the most informative. Here's a link to the section about templates: C++ Templates

Does a constructor also have an implicit this parameter

I am learning about classes in C++ and know that non-static member functions have implicit this parameter. My first question is that does constructor also have an implicit this parameter just like non-static member functions. Note that i am not asking whether we can use this inside a ctor as i already know that we can use this inside a ctor.
Next, I know that inside a const qualified non-static member function for a class X, the type of this is const X*. And for a non-static member function(without const qualified), the type of this is X*. Similarly, inside the ctor the type of this is always X*. Here comes the deeper question.
We know that when we call a non-static member function(say like obj.func()), then the address of the object named obj is implicitly passed to the implicit this parameter of the method func. So this explains "where the this comes from in case of non-static member function".
Now, lets apply the same thing to constructors. For example, say we create an object of class X using default ctor like:
X x; //does the default ctor also have an implicit this parameter to which the address of x is passed?
My second question is: Does the same thing happen to ctors? Like, the address of x is passed to an implicit parameter of the default ctor. My current understanding is that ctors don't have an implicit this parameter. So when we write X x;, the address of x is not passed as an argument because the object is not created yet and so it doesn't make sense to pass its address. But from the standard we know that inside a ctor we can use the this pointer. So my second question essentially is that, if ctors don't have an implicit this parameter then where does the this in the statement this->p = 0; come from? We know that before using any name(like variable name) in C++, we must have a declaration for that name. So where is the declaration for this? Does the compiler implicitly declares the this in case of ctor? I mean, in case of non-static member function, i can understand that they have the declaration for this as the implicit this parameter but what happens in ctors? How inside ctors we're able to use the name this without having a declaration for that?
struct Name
{
private:
int p = 0;
int k = 0;
void func() //func is a non-static member function and so have an implicit this parameter
{
this->k = 0; // the "this" here comes from implicit this parameter
}
Name()
{
this->p = 0; //where does the "this" comes from here since ctor don't have implicit this parameter
}
};
My third question is that is the concept of implicit this parameter an implementation detail or does the standard says that non-static member function will have an implicit this parameter.
Summary
Do ctors have an implicit this parameter? This first question can also be phrased as "Do ctors also have an implicit object parameter?".
The standard says that we can use this inside a ctor. But where does that this come from. For example, in case of a non-static member function, we know that this comes from the implicit this parameter, but in case of ctors, since ctors don't have an implicit this parameter, where does that this that we're allowed to use inside ctor come from.
Is the concept of implicit this parameter an implementation detail or does the standard say that all non-static member functions have an implicit this parameter, in which case, ctors are also allowed by implementations to have an implicit this parameter.
Edit:
The most important part(IMO) of this question is that how are we able to use the name this inside a ctor? For example when we write:
this->p = 0; //here "this" behaves like a name
In the above statement this behaves like a name. And we know that before using any name(like variable name) in C++, we must have a declaration for that name. So where is the declaration for this? Does the compiler implicitly declares the this in case of ctor? I mean, in case of non-static member function, i can understand that they have the declaration for this as the implicit this parameter but what happens in ctors? How inside ctors we're able to use the name this without having a declaration for that?
From the perspective of the C++ standard
The standard only describes the semantics of the this keyword and not how its value gets there. That's completely abstracted away and an implementation has great flexibility in making it happen.
From the perspective of theoretical computer science
The address of the object under construction, available via the this keyword, absolutely is an input to the initialization procedure (called "constructor" in C++) for the object. So are addresses of virtual base subobjects, which C++ also makes available via the this keyword but cannot be calculated from the main input, so any such must be additional inputs.
Note that CS tends to use "parameter" with procedures more in the sense of template parameters than dynamic variable inputs. And CS uses "function" to mean a procedure without side effects. A C++ constructor is not a CS "function" and while templated constructors are possible (parametric procedures) the value of this is an ordinary input not a parameterization.
Neither is a C++ constructor a method -- there is no polymorphic target-type-dependent dispatch, and so in particular the this input is not used for dispatch.
From the perspective of ABI rules for parameter-passing
A C++ constructor is a special member function. There's no way to construct a function pointer for it or invoke it C-style; ABI requirements for C functions do not apply.
If the platform ABI explicitly describes C++ behaviors, then there will be one or more rules for passing the value(s) of this to a C++ constructor. Those rules may or may not specify a mechanism equivalent to other function arguments, but every ABI-compliant C++ compiler targeting that platform will pass this values as required by the special rules for constructors.
Notably, the ABI for passing this to a constructor isn't required to be equivalent to how this is passed to other (non-special and non-static) member functions, although practical ABIs may well use the same approach for both.
There's no such thing as "implicit this parameter" in the standard. The standard calls it an "implicit object parameter".
An implicit object parameter is only relevant to overload resolution, it doesn't "become" this. Separately, this is defined to have the same cv qualification as the member function.
Do ctors have an implicit this parameter? This first question can also be phrased as "Do ctors also have an implicit object parameter?".
No, from [over.match.funcs]
For the purposes of overload resolution, both static and non-static member functions have an implicit object parameter, but constructors do not.
But where does that this come from.
The object being constructed.
Is the concept of implicit this parameter an implementation detail or does the standard say that all non-static member functions have an implicit this parameter, in which case, ctors are also allowed by implementations to have an implicit this parameter.
The implicit object parameter is part of the rules of overload resolution, it doesn't influence this.
How inside ctors we're able to use the name this without having a declaration for that?
this is not a name, it is a language keyword. The language defines this in a non-static member function to be a prvalue expression. Unlike an unqualified-id (that names an object) in the same position, which are glvalue expressions.
That's the language-lawyer answer. Having said that, I do find that "implicit object parameter becomes this" is a useful mental model.
Recall that constructors (and destructors) can't be cv qualified, so there isn't anything for it to distinguish in a constructor, so it doesn't matter if it exists or not.
"this" is a keyword; it doesn't need declaring, but is always available in non-static member functions.
See e.g. the draft standard here.
The keyword this names a pointer to the object for which an implicit object member function is invoked or a non-static data member's initializer is evaluated.
Note that the mechanism behind this is unspecified.

C/C++ - evaluation of the arguments in a function call [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
order of evaluation of function parameters
Is it safe to use the following construction in C/C++?
f(g(), h());
where g() is expected to be evaluated first, then h().
Do all compilers show the same behavior on all architectures?
NO! There is no guarantee what order these are carried out in. Only that both g() and h() are carried out before f().
See this: http://www.gotw.ca/gotw/056.htm
I think there's an updated C++11 version of that, I'll have a look.
Edit: C++11 version http://herbsutter.com/gotw/_102/
Edit 2: If you really want to know what specific compilers do, try this: http://www.agner.org/optimize/calling_conventions.pdf
Section 7 (page 16) may be relevant, though it's a bit over my head, but for instance __cdecl calling convention means arguments are passed from right to left (at least stored that way), whereas for __fastcall "The first two DWORD or smaller arguments are passed in ECX and EDX registers; all other arguments are passed right to left." (http://msdn.microsoft.com/en-us/library/6xa169sk%28v=vs.71%29.aspx)
So it does vary for different compilers.
Much later edit: It turns out that for constructors using the initializer list syntax (curly braces {}), order of evaluation is guaranteed (even if it is a call to a constructor that does not take a std::initializer_list. See this question.
See 1.9 Program execution:
Certain other aspects and operations of the abstract machine are described in this International Standard as
unspecified (for example, order of evaluation of arguments to a function). Where possible, this International
Standard defines a set of allowable behaviors.
and 8.3.6 Default arguments, 9:
[...] Default arguments are evaluated each time the function is called. The order of evaluation of function
arguments is unspecified. Consequently, parameters of a function shall not be used in a default argument,
even if they are not evaluated. [...]
No, it's not safe - if you need a guaranteed order of evaluation, e.g. because of side effects, then you will need to do something like this:
foo = g();
bar = h();
f(foo, bar);
No, the order of evaluation of arguments with respect to each other is unspecified. The only guarantee that you have is that they will not be executed concurrently with each other.
No.
The standard don't define the order of evaluation in that case, and each compiler may do whatever it wants.
I think that most of them (and specially gcc) evaluate the rightest first.

What is the reason for not allowing in C++ a default value for a variable to be a non-static method or member of a class?

I wanted to know why the default value for a variable for a method of a class, cannot be a non-static method or member of the same class.
Is there a reason for that ? Could not the compiler provide to the method the position in the class of the non-static default value ?
I tried to google quickly for an answer but I could not come up with a good answer.
EDIT: here is an example.
This is legal:
class ClassTemp
{
static int s_member;
int MagicOperation(int defaultValue = s_member)
{
return defaultValue;
}
};
But this is not:
class ClassTemp
{
int m_member;
int MagicOperation(int defaultValue = m_member)
{
return defaultValue;
}
};
Default arguments are evaluated in the context of the caller (which is why they are usually called "arguments", not "parameters"), not in the context of the class method. This means that in order to evaluate these non-static arguments the compiler would need to know the specific class instance from which to take these default values.
Of course, it is possible in theory to allow using non-static members as default parameters and make compilers use the class instance that is specified in the member call. But that does not sound like "C++ way" of doing things to me. Also, it might lead to rather convoluted and inelegant specification in some more complicated cases, for example, when the method is virtual.
The non static members are bound to a object and require 'this' pointer to access it . Since this pointer is not available for the default vaules it is not allowed
Off the top of my head, allowing default parameters from the class instance you're calling into, would require "derefing" the member value before making the call, due to function arguments getting pushed on the stack before the this pointer.
Secondly, there would be a small overhead in every call to that method utilizing the default value to the effect of:
push provided arguments...
push (this->member)
push this
These are pretty vague counter arguments, I see no reason why it can't be done either.
If I understand your question, it's because the compiler does know if the non-static variable that you are initializing this method var exists - thus the requirement that it be static so it's guaranteed to exist when the method var is initialized. It's not a matter of looking it up.

C++ - calling methods from outside the class

I have couple questions regarding some C++ rules.
Why am I able to call a function/method from outside the class in the namespace when I include the return type? (look at the namespace test2::testclass2 in the code below) i.e. this works:
bool b = testclass1::foo<int>(2);
whereas this doesn't: - (it doesn't even compile - compiler throws that this is function redeclaration)
testclass1::foo<int>(2);
C++ complains that it is a function redeclaration. Is that so?
This line:
bool b = testclass1::foo<int>(2);
gets called first before anything else. Is this because static methods get created always first before anything else in C++?
Where can I find those rules? I have a few C++ books at home, so if someone would be kind enough to either point out a book (and chapter or page) or direct me to a website I would greatly appreciate it.
Here below is the sample (partial) code that I tested at home with Visual Studio 2008:
class testclass1
{
public:
testclass1(void);
~testclass1(void);
template<class A> static bool foo(int i)
{
std::cout <<"in static foo";
return true;
}
};
namespace test2
{
class testclass2
{
public:
testclass2(void);
~testclass2(void);
};
bool b = testclass1::foo<int>(2);
}
EDIT:
A few people mentioned that I need to call this inside the function and this will work without any problem.
I understand that; the only reason I asked this question is because I saw this code somewhere (in someone's elses project) and was wondering how and why this works. Since I never really seen anyone doing it before.
Also, this is used (in multiple places) as a way to call and instantiate a large number of classes like this via those function calls (that are outside). They get called first before anything else is instantiated.
C++ is not Python. You write statements in functions and execution starts from the main method. The reason bool b = ... happens to work is that it's defining the global variable b and the function call is merely the initialization expression.
Definitions can exist outside functions while other statements can only exist inside a function body.
Why am I able to call a function/method from outside the class in the namespace when I include the return type? (look at the namespace test2::testclass2)
Your declaration of b is not inside a function, so you are declaring a global variable. If you were inside a function's scope, your second statement would work, but outside a function it makes no sense.
This also answers your second question.
Of course, you wouldn't be allowed to call it this way (i.e. not as a method of an object) if it weren't a static member function.
You can find the rules on e.g. Koenig lookup and template in the standard documentation -- good luck with navigating that! You're not mentioning which compiler you are testing, but I'm not entirely sure it's compliant!
As Mehrdad points out, you're declaring and initializing a global variable within the test2 namespace: this has nothing to do with static methods.
if you write this inside a function like below then it works without a problem. As mentioned above, you need to call these functions from within a function unless you are using the function to initialize a global variable ...
int main()
{
testclass1::foo<int>(2);
return 0;
}
1. First, a helpful correction: you said "...when I include the return type". I think you might be misunderstanding what the <int> part of testclass1::foo<int>(2) does. It doesn't (necessarily) specify the return type, it just provides a value for the template argument "A".
You could have chosen to use A as the return type, but you have the return type hard-coded to "bool".
Basically, for the function as you have written it you will always need to have the <> on it in order to call it. C++ does allow you to omit the <args> off the function when the type can be deduced from the function arguments; in order to get it to do that you have to use the type argument A in your function arguments. For instance if you declared the function this way instead then you could call it without the <>:
template<class A> static bool foo(A i);
In which case it you could call "foo(2)" and it would deduce A to be "int" from the number two.
On the other hand there isn't any way to make it deduce anything based on what you assign the function to. For template argument deduction it only looks at the arguments to the function, not what is done with the result of calling the function. So in:
bool b = testclass1::foo(2);
There is no way to get it to deduce "bool" from that, not even if you made A the return type.
So why doesn't the compiler just tell you "you needed to use <> on the function"? Even though you declared foo once as a template function, you could have also overloaded it with a non-template version too. So the compiler doesn't just automatically assume that you're trying to call a template function when you leave the <> off the call. Unfortunately having NOT assumed you were calling template-foo and not seeing any other declaration for foo, the compiler then falls back on an old C style rule where for a function that takes an int and returns an int, in a very old dialect of C you didn't need to declare that kind of before using it. So the compiler assumed THAT was what you wanted - but then it notices that template-foo and old-crufty-C-foo both take an int parameter, and realizes it wouldn't be able to tell the difference between them. So then it says you can't declare foo. This is why C++ compilers are notorious for giving bad error messages - by the time the error is reported the compiler may have gone completely off the rails and be talking about something that is three or four levels removed from your actual code!
2. Yes you're exactly right.
3. I find that the C++ references and whitepapers that IBM makes available online are the most informative. Here's a link to the section about templates: C++ Templates