4
votes

Why does using static template class member as friend template function default parameter give me compile error in c++? How to slove?

Here is the code:

#include <iostream>

template<typename T>
void func(T n);

template<typename T>
class MyClass
{
private:
    static T statTemp;
public:
    friend void func<>(T n);
};

template<typename T>
T MyClass<T>::statTemp(1);

template<typename T>
void func(T n = MyClass<T>::statTemp)
{
    std::cout << n << std::endl;
}

int main()
{
    func<int>();
}

On compile:

g++ -std=c++11 main.cpp

error: redeclaration of 'template<class T> void func(T)' may not have default arguments [-fpermissive]
 void func(T n = MyClass<T>::statTemp)
      ^~~~
In function 'int main()':
error: no matching function for call to 'func<int>()'
  func<int>();
            ^
note: candidate: 'template<class T> void func(T)'
 void func(T n = MyClass<T>::statTemp)
      ^~~~
note:   template argument deduction/substitution failed:
note:   candidate expects 1 argument, 0 provided
  func<int>();
            ^

visual studio 2017

C2672   "func": No matching overloaded function found.
2

2 Answers

2
votes

The language does not allow default arguments for template functions to be added in later declarations of a function in the same scope.

The C++17 standard draft n4659 states :

11.3.6 Default arguments [dcl.fct.default]
...
4 For non-template functions, default arguments can be added in later declarations of a function in the same scope.

Since func is a template function, it is not permitted to add default arguments in later declarations of a func in the same scope.

So GCC correctly rejects this as such:

error: redeclaration of 'template<class T> void func(T)' may not have default arguments [-fpermissive]
 void func(T n = MyClass<T>::statTemp)
0
votes

I got your program to compile, however, I am honestly not sure what it is I really did. I can only take my intuition through it and do the best I can to explain what I just did:

#include <iostream>

template<typename T>
void func();

template<typename T>
class MyClass
{
private:
    static T statTemp;
public:
    friend void func<T>();
};

template<typename T>
T MyClass<T>::statTemp(1);

template<typename T>
void func()
{
    T n = MyClass<T>::statTemp;
    std::cout << n << std::endl;
}

int main()
{
    func<int>();
}

First, I noticed your original funct(T n) you had declared this at the top of the file and it expected a T n to be passed into the function. In main, you do no such thing. So when you call func(T n) and pass nothing into the function, the compiler gets angry since it expects something to be passed in. Maybe what you can do, is overload the function in which calls another func(T n) where you pass it T n = MyClass<T>::statTemp;

Lastly, your friend void func<>() had no template type so the compiler was angry with that as well.

I hope that helps.