Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Function Objects

52 views
Skip to first unread message

Doug Mika

unread,
Apr 30, 2015, 12:46:07 PM4/30/15
to
I have the following short program:

#include<algorithm>
#include<iostream>
#include<vector>
#include<list>

using namespace std;

template<typename T>
void FuncDisplayElement(const T& element){
cout<<element<<' ';
}

template<typename T>
struct DisplayElement{
void operator()(const T& element) const{
cout<<element<<' ';
}
};


int main(int argc, char** argv) {

//The Program
vector<int> vecIntegers;

for(int nCount=0;nCount<10; ++nCount)
vecIntegers.push_back(nCount);

list<char> listChars;

for(char nChar='a'; nChar<'k'; ++nChar)
listChars.push_back(nChar);

DisplayElement<int> de;

cout<<"Displaying the vector of integers"<<endl;
for_each(vecIntegers.begin(),vecIntegers.end(),de);
cout<<endl<<endl;

cout<<"Displaying the vector of integers again"<<endl;
for_each(vecIntegers.begin(),vecIntegers.end(),FuncDisplayElement<int>);
cout<<endl<<endl;

cout<<"Displaying the list of characters"<<endl;
for_each(listChars.begin(),listChars.end(),DisplayElement<char>());


return 0;
}

My question is, why do I need to include the brakets "()" in:
DisplayElement<char>()

when I don't include them in:
de
???

DisplayElement<char> creates an rvalue object of that type, so it is now similar to de, so why the brackets in one but not the other?

Öö Tiib

unread,
Apr 30, 2015, 1:05:17 PM4/30/15
to
Because 'DisplayElement<char>' is type while 'DisplayElement<char>()'
makes temporary object of that type.

> when I don't include them in:
> de
> ???

The 'de' in your code is named object of type 'DisplayElement<int>'.

If you want it to be type 'DisplayElement<int>' then you have
to declare it like:

typedef DisplayElement<int> de;

or in C++11

using de = DisplayElement<int>;

On such cases you need to have brackets with de as well.

> DisplayElement<char> creates an rvalue object of that type, so it
> is now similar to de, so why the brackets in one but not the other?

Where you take that? Not in C++. 'DisplayElement<char>' is just a
type-id like 'int'. You can't use type where object is expected. The
'FuncDisplayElement<int>' is a pointer to function (so object),
'de' is also already existing object and so you need
'DisplayElement<char>()' to create object if you want to pass it
where object belongs in C++.

Richard

unread,
Apr 30, 2015, 1:22:23 PM4/30/15
to
[Please do not mail me a copy of your followup]

Doug Mika <doug...@gmail.com> spake the secret code
<398d6395-bf9c-4ebe...@googlegroups.com> thusly:

>My question is, why do I need to include the brakets "()" in:
>DisplayElement<char>()

DisplayElement<char> is a type.

DisplayElement<char>() is an anonymous temporary instance of the type.

>when I don't include them in:
>de

This is a named instance of the type.
--
"The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline>
The Computer Graphics Museum <http://computergraphicsmuseum.org>
The Terminals Wiki <http://terminals.classiccmp.org>
Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com>

Doug Mika

unread,
Apr 30, 2015, 1:33:49 PM4/30/15
to
well, that's what I thought, but then how can I explain it with the fact that when we have a class with a default (parameterless) constructor, say the class name is Human, I instantiate the class Human on the stack without the use of brackets:

Human someHoman;

NOT
Human someHuman();

Victor Bazarov

unread,
Apr 30, 2015, 1:42:09 PM4/30/15
to
Read up on "most vexing parse".

You *declare* a variable of type T by writing

T <nameofthevariable>;

That's a declaration statement. Depending on the scope in which it
appears it can also be a definition. Definition of an object implies
initialization. Parentheses shift the meaning of the declaration a tiny
bit (again, read up on declaration parsing and it's actually in the FAQ).

V
--
I do not respond to top-posted replies, please don't ask

Doug Mika

unread,
Apr 30, 2015, 2:00:42 PM4/30/15
to
That sort of clears things up. But then, when I declare the anonymous object using:
DisplayElement<int>()

am I declaring it on the stack or the heap? And when and by whom is it deleted?

Öö Tiib

unread,
Apr 30, 2015, 2:04:09 PM4/30/15
to
On Thursday, 30 April 2015 20:33:49 UTC+3, Doug Mika wrote:
> well, that's what I thought, but then how can I explain it with the fact that when we have a class with a default (parameterless) constructor, say the class name is Human, I instantiate the class Human on the stack without the use of brackets:
>
> Human someHoman;

If 'Human' is aggregate (without constructors like DisplayElement<int> is)
then function-local 'someHoman' will be uninitialized variable, it won't
be default constructed. Since 'DisplayElement<int>' is stateless (does not
have non-static data members) it does not matter to it, but generally it
matters.

> NOT
> Human someHuman();

That is function declaration in C++.
When Human is of aggregate type then you need to write:

Human someHaman = Human();

or:

Human someHeman = {};

or since C++11:

Human someHiman{};

to get it default-initialized.

Öö Tiib

unread,
Apr 30, 2015, 2:15:43 PM4/30/15
to
C++ standard does say "automatic storage" (that is usually stack) and
"dynamic storage" (that is usually heap). It does not specify if
temporaries are stored in either (but usually it is stack as well).
Temporary will be destroyed at the end of full expression unless you
initialize reference variable with it. If you initialize reference
variable with it then it will be destroyed when that variable leaves
scope.

Paavo Helde

unread,
Apr 30, 2015, 2:32:31 PM4/30/15
to
Doug Mika <doug...@gmail.com> wrote in
news:18ef5013-3261-45ee...@googlegroups.com:
Because for the compiler this would look like a function declaration. Yes,
it's not fully consistent, that's one of the reasons the new brace
initialization syntax was introduced in C++11 so now you can write:

Human someHuman{};

for defining a variable.

Richard

unread,
Apr 30, 2015, 3:04:07 PM4/30/15
to
[Please do not mail me a copy of your followup]

Doug Mika <doug...@gmail.com> spake the secret code
<f02dd1a2-a8ec-4f3c...@googlegroups.com> thusly:

>That sort of clears things up. But then, when I declare the anonymous
>object using:
>DisplayElement<int>()
>
>am I declaring it on the stack or the heap? And when and by whom is it deleted?

It's on the stack and its lifetime is that of the enclosing
expression, namely the function call where this anonymous instance is
supplied as an actual argument.
Message has been deleted

Öö Tiib

unread,
Apr 30, 2015, 7:03:01 PM4/30/15
to
On Friday, 1 May 2015 01:10:05 UTC+3, Stefan Ram wrote:
> Öö Tiib <oot...@hot.ee> writes:
> >C++ standard does say "automatic storage" (that is usually stack) and
> >"dynamic storage" (that is usually heap).
>
> It always says »automatic storage duration« and »dynamic
> storage duration«.
>
> The difference between »automatic storage« and »automatic
> storage duration« is just like the difference between a »new
> bus« and a »new bus driver« (or a lightning and a lightning bug).
>
> >temporaries are stored in either (but usually it is stack as well).
> >Temporary will be destroyed at the end of full expression unless you
> >initialize reference variable with it. If you initialize reference
> >variable with it then it will be destroyed when that variable leaves
> >scope.
>
> IIRC, this is valid for /const/ lvalue references and for
> rvalue references, but not for /non-const/ lvalue references.

Are these really called "lvalue references" now?
It is impossible to initialize such a reference to non-const with
temporary unless you use Microsoft Visual C or other non-standard
and it seems that at least in visual c it also affects life-time
of temporary.
Message has been deleted

Jorgen Grahn

unread,
May 1, 2015, 1:34:26 PM5/1/15
to
On Thu, 2015-04-30, 嘱 Tiib wrote:
> On Thursday, 30 April 2015 21:00:42 UTC+3, Doug Mika wrote:
...
>> am I declaring it on the stack or the heap? And when
>> and by whom is it deleted?
>
> C++ standard does say "automatic storage" (that is usually stack) and
> "dynamic storage" (that is usually heap). It does not specify if
> temporaries are stored in either (but usually it is stack as well).

Nitpick: might just as well be in registers, or optimized away
partially or completely. Thinking of it as "on the stack" works for
me, but I don't want people to avoid creating classes because they
think using raw ints or whatever is more efficient.

/Jorgen

--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .

Victor Bazarov

unread,
May 1, 2015, 2:03:26 PM5/1/15
to
On 5/1/2015 1:34 PM, Jorgen Grahn wrote:
> On Thu, 2015-04-30, Öö Tiib wrote:
>> On Thursday, 30 April 2015 21:00:42 UTC+3, Doug Mika wrote:
> ...
>>> am I declaring it on the stack or the heap? And when
>>> and by whom is it deleted?
>>
>> C++ standard does say "automatic storage" (that is usually stack) and
>> "dynamic storage" (that is usually heap). It does not specify if
>> temporaries are stored in either (but usually it is stack as well).
>
> Nitpick: might just as well be in registers, or optimized away
> partially or completely. Thinking of it as "on the stack" works for
> me, but I don't want people to avoid creating classes because they
> think using raw ints or whatever is more efficient.

... and don't forget that sometimes it's up to the object itself to use
freestore to deposit some additional information that it needs during
its lifetime (however short). For instance, it's *unlikely* that a
*temporary* vector of [some large number] of elements is all going to
resign in registers or on the stack. You're free to thing of it as "on
the stack", but you will most probably be mistaken. A few bytes on the
stack can mean *any* amount on the heap, as well.

Just a thought...

Jorgen Grahn

unread,
May 2, 2015, 3:48:28 AM5/2/15
to
On Fri, 2015-05-01, Victor Bazarov wrote:
> On 5/1/2015 1:34 PM, Jorgen Grahn wrote:
>> On Thu, 2015-04-30, 嘱 Tiib wrote:
>>> On Thursday, 30 April 2015 21:00:42 UTC+3, Doug Mika wrote:
>> ...
>>>> am I declaring it on the stack or the heap? And when
>>>> and by whom is it deleted?
>>>
>>> C++ standard does say "automatic storage" (that is usually stack) and
>>> "dynamic storage" (that is usually heap). It does not specify if
>>> temporaries are stored in either (but usually it is stack as well).
>>
>> Nitpick: might just as well be in registers, or optimized away
>> partially or completely. Thinking of it as "on the stack" works for
>> me, but I don't want people to avoid creating classes because they
>> think using raw ints or whatever is more efficient.
>
> ... and don't forget that sometimes it's up to the object itself to use
> freestore to deposit some additional information that it needs during
> its lifetime (however short). For instance, it's *unlikely* that a
> *temporary* vector of [some large number] of elements is all going to
> resign in registers or on the stack. You're free to thing of it as "on
> the stack", but you will most probably be mistaken. A few bytes on the
> stack can mean *any* amount on the heap, as well.
>
> Just a thought...

Yes, I was almost about to mention that.

In the end I was unsure why the OP wanted to know. The lifetime
aspect is more important than anything else about this, but I think
others got that message through.

Öö Tiib

unread,
May 2, 2015, 3:07:58 PM5/2/15
to
Such questions are possibly because in C++ there are so lot of syntax
that feels like low level optimization-oriented tinkering. Things like
'inline', 'register', pointers, references, 'std::move', all those
copy and move constructors, assignments etc. That may easily leave
impression that C++ code is somehow in control how the compiler
matches it to instructions, registers, stack and heap of underlying
platform.

Paavo Helde

unread,
May 2, 2015, 6:00:39 PM5/2/15
to
Öö Tiib <oot...@hot.ee> wrote in
news:ee5ee416-a6f7-4e0b...@googlegroups.com:

> On Saturday, 2 May 2015 10:48:28 UTC+3, Jorgen Grahn wrote:
>> On Fri, 2015-05-01, Victor Bazarov wrote:
>> > On 5/1/2015 1:34 PM, Jorgen Grahn wrote:
Sure it is. A large portion of C++ users are relying on its zero-overhead
and maximum performance promises. And for sure, if the performance issues
are critical, the programmer needs to write the code which performs best.
This appears to be still a bit deterministic, so yes, C++ code is
somewhat in control. For example, rvalue references and std::move
specifically fixed a gap in an area which prevented achieving maximum
performance in certain high-level programming style. It is under the
control of the programmer to use or not use this style.

If C++ would at some point fail to follow the zero-overhead principle, a
porton of programmers and programs would move away to some other language
to retain the maximum performance (to Fortran or C, possibly to something
else branched off from C++ (D?)).

Cheers
Paavo


Öö Tiib

unread,
May 2, 2015, 9:04:22 PM5/2/15
to
'register' keyword did mean one day that variable will occupy a register.
Now it only means that one may not take reference of the variable or
parameter. 'inline' keyword did mean one day that the function should
be inlined. Now it only means that defining the function several times
copy-paste in the same program is not ODR violation.
It is so because such decision gave better performance.

Move semantics puts it into programmers hands to indicate if a value
passed will end its duration for next anyway so it may be moved instead
of copied. It may happen that it will be also decay into "hint" one
day that is easier for compiler actually to decide (for better performance).

> If C++ would at some point fail to follow the zero-overhead principle, a
> porton of programmers and programs would move away to some other language
> to retain the maximum performance (to Fortran or C, possibly to something
> else branched off from C++ (D?)).

I did not mean that C++ is adding or should start adding any overhead. I
mean that the programmers somehow manage to add complications and so
cause overhead with anything.
0 new messages