C++ static template class member as friend 模板函数默认参数

C++ static template class member as friend template function default parameter

为什么在 C++ 中使用静态模板 class 成员作为友元模板函数默认参数会出现编译错误?如何解决?

代码如下:

#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>();
}

编译时:

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.

我编译了你的程序,但是,老实说,我不确定我到底做了什么。我只能凭借我的直觉,尽我所能解释我刚刚做了什么:

#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>();
}

首先,我注意到您原来的 funct(T n) 您已在文件顶部声明了它,它希望将 T n 传递到函数中。总的来说,你不会做这样的事情。因此,当您调用 func(T n) 并且没有向函数传递任何内容时,编译器会生气,因为它希望传递一些东西。也许您可以做的是重载调用另一个 func(T n) 的函数通过它 T n = MyClass<T>::statTemp;

最后,您的 friend void func<>() 没有模板类型,因此编译器对此也很生气。

希望对您有所帮助。

该语言不允许将模板函数的默认参数添加到同一范围内函数的后续声明中。

C++17 标准草案 n4659 指出:

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.

由于 func 是模板函数,因此不允许在同一范围内的 func 的后续声明中添加默认参数。

所以 GCC 正确地拒绝了这个:

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