4

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.
so_Orange
  • 63
  • 5

2 Answers2

2

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)
P.W
  • 26,289
  • 6
  • 39
  • 76
  • Could I move the default parameter value from definition to declaration? It seems that the compilation was successful, but is thedeclarators allowed to do so? template void func(T n = MyClass::statTemp); – so_Orange Feb 25 '19 at 05:13
  • 1
    Yes you can have default parameters in template function declarations. – P.W Feb 25 '19 at 05:20
  • I found a different situation: If I use [Page 776 · Chapter 14 · Unbound Template Friend Functions to Template Classes](https://doc.lagout.org/programmation/C%2B%2B/C%2B%2B_Primer_Plus_(5th_Edition).pdf#page=799&zoom=page-fit,-287,697) like this: `template class MyClass { public: static T statTemp;template friend void func(V n); }; template void func(T n) {}` Where can I add a default parameter? There seems to be no declaration, only definition. – so_Orange Feb 25 '19 at 05:50
  • 1
    In that case, you can have a default parameter in the definition itself. – P.W Feb 25 '19 at 05:56
  • See the section on "Default template arguments" in this page for more info: https://en.cppreference.com/w/cpp/language/template_parameters – P.W Feb 25 '19 at 13:28
  • `template class MyClass { private: static T statTemp; public: friend void func1(int m); template friend void func2(V n); }; template T MyClass::statTemp{ 1 }; void func1(int m = MyClass::statTemp) {} template void func2(T n = MyClass::statTemp) {} int main() { func2(); return 0; }` This code failed to compile in g++ (_may not have default arguments_). If I remove `func1`, it will compile successfully. – so_Orange Feb 25 '19 at 14:13
  • 1
    You have a declaration of func2 without default argument inside the template AND a definition of func2 with default argument outside​ the template. This is not allowed. – P.W Feb 25 '19 at 14:23
0

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.

Sailanarmo
  • 1,139
  • 15
  • 41
  • I'm reading [Page 773 · Chapter 14 · Bound Template Friend Functions to Template Classes](https://doc.lagout.org/programmation/C%2B%2B/C%2B%2B_Primer_Plus_(5th_Edition).pdf#page=796&zoom=page-fit,-287,713), the code on book doesn't have a default parameter value, **I'm try to add a default parameter value** but failed. This makes me confused. – so_Orange Feb 25 '19 at 04:49