instantiating a "function type" variable

Viewed 73

In the 3 code snippets below, only the first one is accepted by the compiler, while the second and third aren't. I think all three cases are essentially doing the same thing: I am instantiating a variable of type "int(int,int)". Why it's okay to use int(int,int) instead of int(*)(int,int) in a template, when it doesn't work anywhere else?

First

#include<iostream>
#include<list>
#include<numeric>
using namespace std;

template<typename T>
T func(T first, T second)
{
    return first+second;
}

int main()
{
    list<int> l;
    l.push_back(2);
    l.push_front(1);
    l.push_back(3);
    l.push_back(4);

    cout << accumulate<list<int>::iterator, int, typeof(func<int>)>(l.begin(),l.end(),0,func<int>);
    return 0;
}

The source code for the accumulate function in numeric library:

    template<typename _InputIterator, typename _Tp,
    typename _BinaryOperation>
    _Tp accumulate(_InputIterator __first, _InputIterator __last,
    _Tp __init, _BinaryOperation __binary_op)
    {
        for ( ; __first != __last; ++__first)
        __init = __binary_op(__init, *__first);
        return __init;

Second

#include<iostream>
#include<list>
using namespace std;

template<typename T>
T func(T x, T y)
{
    return x;
}

typedef int _BinaryOperation (int, int);

int main()
{
    _BinaryOperation __binary_op = func<int>;
    return 0;
}

Third

#include<iostream>
#include<list>
#include<numeric>
using namespace std;

template<typename T>
T func(T x, T y)
{
    return x+y;
}

int main()
{
    int (*pt)(int, int) = &(func<int>);
    cout << (*pt)(2,2); 

    int func_(int, int) = func<int>; //error
    return 0;
}

1 Answers

In C++ standard 1.1.8.1 it is written

The constructs in a C++ program create, destroy, refer to, access, and manipulate objects. An object is a region of storage. [ Note: A function is not an object, regardless of whether or not it occupies storage in the way that objects do. — end note ] An object is created by a definition (3.1), by a new-expression (5.3.4) or by the implementation (12.2) when needed. The properties of an object are determined when the object is created. An object can have a name (Clause 3). An object has a storage duration (3.7) which influences its lifetime (3.8). An object has a type (3.9). The term object type refers to the type with which the object is created. Some objects are polymorphic (10.3); the implementation generates information associated with each such object that makes it possible to determine that object’s type during program execution. For other objects, the interpretation of the values found therein is determined by the type of the expressions (Clause 5) used to access them

Here in the second and third examples, you are trying to treat functions as objects, by which you try to declare functions of certain type, and instantiate functions and treat them as objects.

But the function pointer, contrary to a function, IS AN OBJECT, so the following line

int (*pt)(int, int) = &(func<int>);

is valid because you take pointers, which are objects. This line is also valid.

int (*pt)(int, int) = func<int>;

Because in such an expression, func<int> is implicitly converted to a function pointer.

Related