Compiling error with function pointer

I try to use a function pointer with template, but I encounter a problem with PGI C++ version new than 9.0. The code is as below.

#include <iostream>
#include <iomanip>
#include <cmath>

using namespace std;

template <class>
struct test
{
    typedef void (*Cptr[2])(T3 a, T4 b);
};

template <class>
void add(T3 a, T4 b)
{
    cout << "\nAdd" << a << " and " << b;
    return;
};

template <class>
void mi(T3 a, T4 b)
{
    cout << "\nMinus" << a << " and " << b;
    return;
};

template <class>
void assigntest(void (*Cptr[2])(T3 a, T4 b))
{
    Cptr[0] = add<T3>;
    Cptr[1] = mi<T3>;
    return;
};

template <class>
void TestingRegion(T3 a, T4 b)
{
    test<T3>::Cptr object;
    assigntest(object);
    add(a, b);
    mi(a,b);
    return;
}

int main()
{
    double a = 1.0, b = 2.0;
    int c = 3, d = 4, flag = 0;

    TestingRegion(a,b);
    TestingRegion(c,d);    

    return 0;
}

The above codes work fine with PGI C++ 9.0, but it encounter error in version > 10.0 with the following message:

"test.cpp", line 46: error: expected a ";"
      test<T3>::Cptr object;
                         ^

"test.cpp", line 47: error: identifier "object" is undefined
      assigntest(object);
                 ^

"test.cpp", line 47: error: no instance of function template "assigntest"
          matches the argument list
            argument types are: (<error>)
      assigntest(object);
      ^

3 errors detected in the compilation of "test.cpp".

I used the same option to compile in both versions (-Kieee -fastsse -Mipa=fast,inline -mp -w). What should I do to correct this problem?

Hi garlam,

Can you double check that the code posted is correct? I get the following errors with both pgcpp (all versions) and g++.

% g++ test.cpp
test.cpp:10: error: ‘T3’ has not been declared
test.cpp:10: error: ‘T4’ has not been declared
test.cpp:14: error: variable or field ‘add’ declared void
test.cpp:14: error: template declaration of ‘int add’
test.cpp:14: error: ‘T3’ was not declared in this scope
test.cpp:14: error: ‘T4’ was not declared in this scope
test.cpp:21: error: variable or field ‘mi’ declared void
test.cpp:21: error: template declaration of ‘int mi’
test.cpp:21: error: ‘T3’ was not declared in this scope
test.cpp:21: error: ‘T4’ was not declared in this scope
test.cpp:28: error: variable or field ‘assigntest’ declared void
test.cpp:28: error: template declaration of ‘int assigntest’
test.cpp:28: error: ‘Cptr’ was not declared in this scope
test.cpp:28: error: ‘T3’ was not declared in this scope
test.cpp:28: error: ‘T4’ was not declared in this scope
test.cpp:28: error: void value not ignored as it ought to be
test.cpp:36: error: variable or field ‘TestingRegion’ declared void
test.cpp:36: error: template declaration of ‘int TestingRegion’
test.cpp:36: error: ‘T3’ was not declared in this scope
test.cpp:36: error: ‘T4’ was not declared in this scope
test.cpp: In function ‘int main()’:
test.cpp:50: error: ‘TestingRegion’ was not declared in this scope

Thanks,
Mat

It seems that it is a problem when I copy & paste the code here.

The code should be

#include <iostream> 
#include <iomanip> 
#include <cmath> 

using namespace std; 

template <class T3, class T4> 
struct test 
{ 
    typedef void (*Cptr[2])(T3 a, T4 b); 
}; 

template <class T3, class T4> 
void add(T3 a, T4 b) 
{ 
    cout << "\nAdd" << a << " and " << b; 
    return; 
}; 

template <class T3, class T4> 
void mi(T3 a, T4 b) 
{ 
    cout << "\nMinus" << a << " and " << b; 
    return; 
}; 

template <class T3, class T4> 
void assigntest(void (*Cptr[2])(T3 a, T4 b)) 
{ 
    Cptr[0] = add<T3>; 
    Cptr[1] = mi<T3>; 
    return; 
}; 

template <class T3, class T4> 
void TestingRegion(T3 a, T4 b) 
{ 
    test<T3>::Cptr object; 
    assigntest(object); 
    add(a, b); 
    mi(a,b); 
    return; 
} 

int main() 
{ 
    double a = 1.0, b = 2.0; 
    int c = 3, d = 4, flag = 0; 

    TestingRegion(a,b); 
    TestingRegion(c,d);    

    return 0; 
}

Hi garlam,

The code "test<T3,T4::Cptr object; " (the missing > is intensional) is ambiguous since it could be a type or a data member. The 9.0 compiler was not correctly discovering this.

The fix is is to use the typename keyword. “typename test<T3,T4::Cptr object;”.

Note that without “typename”, the code will fail to compiler with g++ as well.

Hope this helps,
Mat

Note that our user forum software has problems when multiple strings are enclosed in “<>”.

Hi Mat,

It works like charm. Thanks a lot! I can now apply function pointer together with template in my code.