1

So I have a class that takes two template parameters, one is the type, one is the type of the function used, it has a reduce function to apply this function repeatedly to the array. However, I'm getting a compilation error.

function_template_test.cpp: In instantiation of 'class _C<int, int(int, int)>':
function_template_test.cpp:36:33:   required from here
function_template_test.cpp:11:17: error: field '_C<int, int(int, int)>::op' invalidly declared function type
  BinaryOperator op;

Here is my code. I have a class and the driver code down below in the main method.

#include<iostream>
template<typename _T>
_T addition(_T x,_T y)
{
    return x+y;
}
template<typename _T,typename BinaryOperator>
class _C
{
private:
    BinaryOperator op;
public:
    _C(BinaryOperator op)
    {
        this->op=op;
    }
    _T reduce(_T*begin,_T*end)
    {
        _T _t_=*begin;
        ++begin;
        while(begin!=end)
        {
            _t_=this->op(_t_,*begin);
            ++begin;
        }
        return _t_;
    }
    _T operator()(_T*begin,_T*end)
    {
        return this->reduce(begin,end);
    }
};
int main(int argl,char**argv)
{
    int arr[]={1,4,5,2,9,3,6,8,7};
    _C<int,decltype(addition<int>)>_c_=_C<int,decltype(addition<int>)>(addition<int>);
    std::cout<<_c_(arr,arr+9)<<std::endl;
    return 0;
}

2 Answers2

3

You're specifying function type as the template argument for BinaryOperator, which can't be used as the data member op's type; you can specify function pointer type instead. e.g.

_C<int,decltype(addition<int>)*>_c_=_C<int,decltype(addition<int>)*>(addition<int>);
//                            ^                                   ^

BTW: Names like _C beginning with an underscore are reserved in C++.

songyuanyao
  • 169,198
  • 16
  • 310
  • 405
  • Also I noticed that in the standard library a lot of stuff had underscores in front of them, so I started using them, I didn't know they were reserved. – DSOI__UNUNOCTIUM Dec 09 '19 at 03:45
  • 4
    @DSOI__UNUNOCTIUM Yes, they're reserved for libraries, to avoid conflict between library implementations and your own. – songyuanyao Dec 09 '19 at 03:49
2

Normally when assigning a function to a function pointer you don't explicitly need to add the address of operator (&) as it is not valid to assign the function itself to a variable so the language automatically adds it for you. However when doing decltype on a function name you do get the function type not a function pointer. For example try compiling the following, all the static_asserts should pass:

#include <type_traits>

void foo() {}

int main()
{
    auto a = foo;
    auto b = &foo;
    static_assert(std::is_same_v<decltype(a), decltype(b)>,"a and b are function pointers");
    static_assert(!std::is_same_v<decltype(a), decltype(foo)>,"foo is not a function pointer");    
    static_assert(std::is_same_v<decltype(a), decltype(&foo)>,"&foo is a function pointer");    
}

Your code is essentially equivalent to:

#include <type_traits>

void foo() {}

int main()
{
    decltype(foo) c = foo;
}

Which doesn't compile. Changing it to this fixes the problem:

#include <type_traits>

void foo() {}

int main()
{
    decltype(&foo) c = foo;
}

The fix to your code is to change it to:

_C<int,decltype(&addition<int>)>_c_=_C<int,decltype(&addition<int>)>(addition<int>);

Or you can avoid repeating the types by just constructing directly:

_C<int,decltype(&addition<int>)>_c_(addition<int>);

Or using auto:

auto _c_=_C<int,decltype(&addition<int>)>(addition<int>);
Alan Birtles
  • 32,622
  • 4
  • 31
  • 60