Член класса статического шаблона C ++ в качестве параметра по умолчанию для функции шаблона друга

Почему использование статического члена класса шаблона в качестве параметра по умолчанию для функции шаблона друга дает мне ошибку компиляции в c ++? Как любить?

Вот код:

#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.

person so_Orange    schedule 25.02.2019    source источник


Ответы (2)


Язык не позволяет добавлять аргументы по умолчанию для функций шаблона в более поздние объявления функции в той же области.

В стандартном проекте N4659 C ++ 17 говорится:

11.3.6 Аргументы по умолчанию [dcl.fct.default]
...
4 Для функций, не являющихся шаблоном, аргументы по умолчанию могут быть добавлены в более поздние объявления функции в той же области.

Поскольку 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)
person P.W    schedule 25.02.2019
comment
Могу ли я переместить значение параметра по умолчанию из определения в объявление? Кажется, что компиляция прошла успешно, но разрешено ли это делать деклараторам? шаблон ‹typename T› void func (T n = MyClass ‹T› :: statTemp); - person so_Orange; 25.02.2019
comment
Да, вы можете иметь параметры по умолчанию в объявлениях функций шаблона. - person P.W; 25.02.2019
comment
Я обнаружил другую ситуацию: если я использую стр. 776 · Глава 14 · Несвязанные функции друзей шаблона для классов шаблонов следующим образом: template<typename T> class MyClass { public: static T statTemp;template<typename V> friend void func(V n); }; template<typename T> void func(T n) {} Где я могу добавить параметр по умолчанию? Кажется, что нет декларации, только определение. - person so_Orange; 25.02.2019
comment
В этом случае у вас может быть параметр по умолчанию в самом определении. - person P.W; 25.02.2019
comment
Дополнительную информацию см. В разделе «Аргументы шаблона по умолчанию» на этой странице: en.cppreference.com/ w / cpp / language / template_parameters - person P.W; 25.02.2019
comment
template<typename T> class MyClass { private: static T statTemp; public: friend void func1(int m); template<typename V> friend void func2(V n); }; template<typename T> T MyClass<T>::statTemp{ 1 }; void func1(int m = MyClass<int>::statTemp) {} template<typename T> void func2(T n = MyClass<T>::statTemp) {} int main() { func2<double>(); return 0; } Этот код не удалось скомпилировать в g ++ (может не иметь аргументов по умолчанию). Если я удалю func1, он успешно скомпилируется. - person so_Orange; 25.02.2019
comment
У вас есть объявление func2 без аргумента по умолчанию внутри шаблона И определение func2 с аргументом по умолчанию вне шаблона. Это не разрешено. - person P.W; 25.02.2019

Я попросил вашу программу скомпилировать, однако, честно говоря, я не уверен, что именно я сделал на самом деле. Я могу только проникнуться интуицией и сделать все, что в моих силах, чтобы объяснить то, что я только что сделал:

#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<>() не было типа шаблона, поэтому компилятор тоже рассердился на это.

Надеюсь, это поможет.

person Sailanarmo    schedule 25.02.2019
comment
Я читаю Стр. 773 · Глава 14 · Связанные функции друзей шаблона с классами шаблонов, код в книге не имеет значения параметра по умолчанию, Я пытаюсь добавить значение параметра по умолчанию но не удалось. Это меня смущает. - person so_Orange; 25.02.2019