определить не шаблонную функцию вне шаблонного класса - PullRequest
2 голосов
/ 24 января 2020

Я узнал о функции друга без шаблона и функции друга с шаблоном в шаблонном классе. Поэтому я попробовал приведенный ниже код:

#include <iostream>   


template<typename T>
class  cl
{
private :
    T val;
public:
    cl()= default;
    explicit cl(T v) : val(std::move(v)) {}    

    friend void non_template_friend(cl m);
};

template <typename T>
void non_template_friend(cl<T> m)  { std::cout << m.val << std::endl;}


int main()
{

    cl<int> c(10);
    non_template_friend(c);
    return 0;
}

, поэтому при компиляции я получил: undefined reference to non_template_friend (cl) '`Итак, чтобы решить, что мне нужно переместить определение функции-друга в определение класса, вот так :

template<typename T>
class  cl
{
private :
    T val;
public:
    cl()= default;
    explicit cl(T v) : val(std::move(v)) {}    

    friend void non_template_friend(cl m) { std::cout << m.val << std::endl;}
};

Но мне было интересно, есть ли какая-нибудь хитрость, чтобы можно было определить поведение друга вне определения класса?

Спасибо.

Ответы [ 2 ]

5 голосов
/ 24 января 2020

Если вы хотите определить определение вне класса, оно должно быть функцией шаблона, так как оно должно быть способно принимать любой тип c1.

Вы можете достичь этого, объявив как класс, так и функция.

#include <iostream>

template<typename T>
class  cl;

template<typename T>
void non_template_friend(cl<T> m);

template<typename T>
class  cl
{
private :
    T val;
public:
    cl()= default;
    explicit cl(T v) : val(std::move(v)) {}    

    friend void non_template_friend<T>(cl m); //Now we can refer to a specific instatiation of the template  here
};

template <typename T>
void non_template_friend(cl<T> m)  { std::cout << m.val << std::endl;}


int main()
{

    cl<int> c(10);
    non_template_friend(c);
    return 0;
}
1 голос
/ 24 января 2020

В первой программе

template<typename T>
class  cl
{
private :
    T val;
public:
    cl()= default;
    explicit cl(T v) : val(std::move(v)) {}    

    friend void non_template_friend(cl m);
};

template <typename T>
void non_template_friend(cl<T> m)  { std::cout << m.val << std::endl;}

Вы объявили функцию друга без шаблона, но затем вы объявили и определили функцию шаблона с тем же именем /

Функция друга без шаблона объявление означает, что если вы должны предоставить набор перегруженных не шаблонных функций для специализаций шаблона класса /

Вот демонстрационная программа.

#include <iostream>
template<typename T>
class  cl
{
private :
    T val;
public:
    cl()= default;
    explicit cl(T v) : val(std::move(v)) {}    

    friend void non_template_friend(cl m) ;
};

void non_template_friend( cl<int> m)  { std::cout << m.val << std::endl;}
void non_template_friend( cl<double> m)  { std::cout << m.val << std::endl;}

int main() 
{
    cl<int> c(10);
    non_template_friend(c);

    cl<double> c2( 20.2 );
    non_template_friend(c2);


    return 0;
}

Вывод программы:

10
20.2

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

...