друг специализированного шаблонного класса (C ++) - PullRequest
3 голосов
/ 16 декабря 2011
#include <iostream>
using namespace std;
template <typename T>
class test
{
    T y;

public:
    test(T k) : y(k) {}
    friend int a(T& x);
};

template <typename T>
int a(T& x)
{
    cout << x.y;
    return 9;
}

template <>
class test<int>
{
    int y;
public:
    test(int k) : y(k) {}
    friend int a(int& x);
};

template <>
int a<int>(int& x)
{
    cout << "4";
    return 0;
}

int main(int argc, char* argv[])
{
    test<int> z(3);
    a(z);

    return 0;
}

Я хочу сделать класс друга тестовым классом (в реальном случае это был оператор << ofstream). Но я понятия не имею, как определить шаблонную функцию друга специализированного класса. </p>

Кроме того, код выше показывает это сообщение об ошибке компиляции;

ошибка C2248: 'test :: y': невозможно получить доступ к закрытому члену, объявленному в класс "тест"

Вопрос добавлен;

У меня отлично работает Аарон МакДейд, но я пытался перегрузить оператор << класса ofstream. </p>

friend ofstream& operator<< <test<int>> (ofstream& os, const test<int>& t);

Я добавил код выше для проверки класса и

template<>
ofstream& operator<< <test<int> > (ofstream& os, const test<int>& t)
{
    os << t.y;
    return os;
}

использованный код выше. Но, похоже, я не могу использовать os << t.y (<em> int ). Я не понимаю, почему это происходит. Сообщение об ошибке

ошибка C2027: использование неопределенного типа 'std :: basic_ofstream <_Elem, _Traits>'

Ответы [ 3 ]

4 голосов
/ 16 декабря 2011

Этот друг не шаблон, а обычная функция:

friend int a(T& x); 

Чтобы иметь шаблон, который также является другом, попробуйте:

template<class U>
friend int a(U& x); 

Послеобсуждения в комментариях, возможно, я должен показать, что я предназначил эти объявления для класса test и его специализации:

template <typename T>
class test
{
    T y;

public:
    test(T k) : y(k) {}

    template<class U>
    friend int a(U& x); 
};

template <>
class test<int>
{
    int y;
public:
    test(int k) : y(k) {}

    template<class U>
    friend int a(U& x); 
};

Небольшой недостаток в том, что это делает все функции a друзьями всехtest классы, но это часто не большая проблема.

2 голосов
/ 16 декабря 2011

( Обновление : вот полностью протестированная версия для http://ideone.com/3KGU4. Для Дополнительный вопрос , см. http://ideone.com/w0dLo)

Существует разница междуобычные перегруженные функции и функции шаблонов. Например, без ссылки на шаблоны разработчик может объявить:

void f(int x);
void f(char *x);

В качестве альтернативы разработчик может использовать шаблоны,

template <class T> void f(T x);

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

Позже в вашей программе,ясно, что вы хотите, чтобы a была функцией шаблона, а не просто (перегруженной) обычной функцией. Но когда компилятор впервые видит упоминание a (вокруг строки 10), он выглядит так, как будто он объявляет обычную функциюЧтобы решить эту проблему, вы должны сделать два шага. Вы должны как можно скорее объявить, что a является функцией шаблона, поэтому ваша первая строкадолжно быть:

template <typename T> int a(T& x);

Тогда вы должны объявить соответствующую дружбу.Если T равно int, то a принимает параметр test<int>&, а не int&.Поэтому две строки друзей следует заменить на:

friend int a<test<T> >( test<T> & x); // around line 10
friend int a<test<int> >( test<int> & x); // around line 27

, а специализация a должна быть:

template <>
int a< test<int> >(test<int>& ) // around line 30

Дополнительный вопрос

Используйте ostream вместо ofstream (или включите #include <fstream>, если вы будете выводить только файлы, а не cout).В моем ответе operator << - это не шаблон, а обычная перегруженная функция.Я не уверен, что возможно иметь operator<< в качестве шаблона.Также я определил оператора в том месте, где он объявлен и объявлен как друг.Если честно, я думаю, что есть и другие, может быть, и более эффективные способы, но у меня это сработало.

0 голосов
/ 16 декабря 2011

Попробуйте, и работает

#include <iostream>
using namespace std;

template <typename T>
class test;

template <typename T>
int a( test<T>& x);

template <typename T>
class test
{
    T y;

public:
    test(T k) : y(k) {}
    friend int a<T>( test<T>& x);
};

template <typename T>
int a( test<T>& x)
{
    cout << x.y;
    return 9;
}

template <>
class test<int>
{
    int y;
public:
    test(int k) : y(k) {}

    friend int a<int>( test<int> & x);
};

template <>
int a< int >( test<int> & x)
{
    cout << "4";
    return 0;
}

int main(int argc, char* argv[])
{
    test<int> z(3);
    a(z);

    return 0;
}

Проблема в том, что шаблонная функция a принимает параметр test шаблонного класса.Если вы хотите, чтобы у них обоих был один и тот же аргумент шаблона, тогда, IMO, вам нужно явно указать, что

template <typename T>
    int a( test<T>& x);

Также специализация функции a для int (template<> int a(int& x)) не полезнаВот.Вам нужно иметь

template <> int a<int>( test<int> & x)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...