Error: expected nested-name-specifier before 'dn_dxn'

I may simply be too tired, so I'm not figuring this out. I'm working with templates for the first time. I've developed an algorithm to accept a function given an arbitrary number of variables (passed through an array) and numerically differentiate it an arbitrary number of times. I'm trying to template it so that it can pass and receive a few combinations of double and long double types. I'm also trying to implement the explicit instantiation as described in http://www.cplusplus.com/forum/articles/14272/ .

HAM.h
1
2
3
4
5
6
7
8
9
10
#ifndef HAM_H
#define HAM_H

// Functions for solving non-linear systems using Homotopy Analysis Method

template <typename T, typename U> T dn_dxn(unsigned int n, T (*f)(U[]), U args[], unsigned int narg);
template <typename T, typename U> T nCr(T n, U k);
template <typename T> T factorial(T n);

#endif // HAM_H 


HAM.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <cmath>
#include "HAM.h"

//num_t dn_dxn(level of differentiation, base function, base function argument array, which argument to differentiate)
template <typename T, typename U>
T dn_dxn(unsigned int n, T (*f)(U[]), U args[], unsigned int narg)
{
    T h = pow(1e-9, 1 / n);  // Smallest reasonable change in x; Value determined by experimentation.
    T sum = 0;

    for (unsigned int k = 0; k <= n; k++)
    {
        args[narg] += (n / 2 - k) * h;
        sum += pow(-1, k) * nCr(n, k) * f(args);
        args[narg] -= (n / 2 - k) * h;
    }

    return sum / pow(h, n);
}

template <typename T, typename U>
T nCr(T n, U k)
{
    return factorial(n) / (factorial(k) * factorial(n - k));
}

template <typename T>
T factorial(T n)
{
    if (n < 0)
        return NAN;
    else if (n == 0)
        return 1;
    else
        return(n * factorial(n-1));
}

template typename dn_dxn<long double, long double>;
template typename dn_dxn<long double, double>;
template typename dn_dxn<double, long double>;
template typename dn_dxn<double, double>;

template typename nCr<unsigned int, unsigned int>;
template typename nCr<unsigned int, unsigned long>;
template typename nCr<unsigned long, unsigned int>;
template typename nCr<unsigned long, unsigned long>;

template typename factorial<unsigned int>;
template typename factorial<unsigned long>;


Line 38: Error: expected nested-name-specifier before 'dn_dxn'
Line 38: Error: template-id 'dn_dxn<long double, long double>' used as declarator
Line 38: Error: 'dn_dxn(unsigned int, T (*)(U*), U*, unsigned int)' is not a variable template
(Analogous errors for the remaining templates.)
Last edited on
template <> double dn_dxn(unsigned int n, double (*f)(double[]), double args[], unsigned int narg);

etc.

But wouldn't you be better just defining the entire template function in the .h file?
Last edited on
These are function templates; a few explicit instantiation declarations and definitions would be:

1
2
3
4
5
// explicit instantiation declarations (in the header)

extern template unsigned long factorial( unsigned long ) ;
extern template unsigned int nCr( unsigned int, unsigned int );
extern template double dn_dxn( unsigned int, double(*)(double[]), double[], unsigned int ) ;

and
1
2
3
4
5
// explicit instantiation definitions (in the cpp file)

template unsigned long factorial( unsigned long ) ;
template unsigned int nCr( unsigned int, unsigned int );
template double dn_dxn( unsigned int, double(*)(double[]), double[], unsigned int ) ;


For more information, see 'Explicit instantiation' in: https://en.cppreference.com/w/cpp/language/function_template
Thank you. I wasn't putting the full function in the .h file because, as I've understood it from my formal programming classes, writing executed code in a header is considered bad practice.

However, I still have problems. Using the format above, I now get the error in the header "error: 'dn_dxn' is not a template function. In the .cpp, I'm getting "error: there is no arguments to 'nCr' that depend on a template parameter, so a declaration of 'nCr' must be available [-fpermissive]"
> I wasn't putting the full function in the .h file because, as I've understood it from my formal
> programming classes, writing executed code in a header is considered bad practice.

It is ok for to define function templates in the header.
A function template by itself is not a type, or a function, or any other entity. No code is generated from a source file that contains only template definitions. In order for any code to appear, a template must be instantiated: the template arguments must be determined so that the compiler can generate an actual function (or class, from a class template).

https://en.cppreference.com/w/cpp/language/function_template

Place the template definitions in the header, and let the templates be implicitly instantiated (unless there is a specific reason not to do so).

As an aside, avoid specialising function templates with template<>, it is almost always a bad idea.
See: http://www.gotw.ca/publications/mill17.htm



Sorry, @rcx11, I was incorrect to put the angle brackets in: @JLBorges gives the correct syntax and arrangement between .h and .cpp files.

I usually put templates in the .h file and don't have to worry about the explicit instantiations, so I simply got it wrong in this instance.

Good luck.
Thank you, all. This is coming together but I'm still receiving "Line 16: error: there is no arguments to 'nCr' that depend on a template parameter, so a declaration of 'nCr' must be available [-fpermissive]". Thoughts?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#ifndef HAM_H
#define HAM_H

// Functions for solving non-linear systems using Homotopy Analysis Method

//num_t dn_dxn(level of differentiation, base function, base function argument array, which argument to differentiate)
template <typename T, typename U>
T dn_dxn(unsigned int n, T (*f)(U[]), U args[], unsigned int narg)
{
    T h = pow(1e-9, 1 / n);  // Smallest reasonable change in x; Value determined by experimentation.
    T sum = 0;

    for (unsigned int k = 0; k <= n; k++)
    {
        args[narg] += (n / 2 - k) * h;
        sum += pow(-1, k) * nCr(n, k) * f(args);
        args[narg] -= (n / 2 - k) * h;
    }

    return sum / pow(h, n);
}

template <typename T, typename U>
T nCr(T n, U k)
{
    return factorial(n) / (factorial(k) * factorial(n - k));
}

template <typename T>
T factorial(T n)
{
    if (n < 0)
        return NAN;
    else if (n == 0)
        return 1;
    else
        return(n * factorial(n-1));
}

#endif // HAM_H 
Declare the function right at the top:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef HAM_H
#define HAM_H

#include <cmath> // for std::pow

// Functions for solving non-linear systems using Homotopy Analysis Method

//////////////// added /////////////////////////////////////
template <typename T, typename U> T nCr(T n, U k) ;
template <typename T> T factorial(T n) ;
////////////////////////////////////////////////////////////

//num_t dn_dxn(level of differentiation, base function, base function argument array, which argument to differentiate)
template <typename T, typename U>
T dn_dxn(unsigned int n, T (*f)(U[]), U args[], unsigned int narg)
{
// ... 
Success! Thank you, all!

On the note of templates, is there a way to make certain data types off limits? (In this, the nCr and Factorial functions are only applicable to integers >= 0.)
Last edited on
We could use SFINAE (std::enable_if) https://en.cppreference.com/w/cpp/types/enable_if

Or, probably simpler, a static assertion: https://en.cppreference.com/w/cpp/language/static_assert

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>
#include <type_traits> // https://en.cppreference.com/w/cpp/types/is_integral

// enabled if and only if INT_TYPE is an integral type
template < typename INT_TYPE > constexpr
 typename std::enable_if< std::is_integral<INT_TYPE>::value, unsigned long long >::type
factorial( INT_TYPE n )
{ return n < 2 ? 1 : n * factorial(n-1) ; }

// static assertion fails if INT_TYPE is not an integral type
template < typename INT_TYPE > constexpr
unsigned long long factorial_2( INT_TYPE n )
{
    static_assert( std::is_integral<INT_TYPE>::value, "an integral type is required" ) ;
    return n < 2 ? 1 : n * factorial_2(n-1) ;
}

int main()
{
    std::cout << factorial(12) << '\n' ; // 479001600
    std::cout << factorial_2(12) << '\n' ; // 479001600

    std::cout << factorial(-3) << '\n' ; // 1
    std::cout << factorial_2(-3) << '\n' ; // 1

    // factorial(10.3) ; // *** error: no matching function
    // factorial_2(10.3) ; // *** error: static_assert failed: "an integral type is required"
}
Topic archived. No new replies allowed.