специализация на шаблонах, c ++ - PullRequest
0 голосов
/ 22 сентября 2011

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

#ifndef STORAGE_HPP_
#define STORAGE_HPP_

#include <iostream>

using namespace std;

template <typename T, int size> class Storage
{ //LINE 16 ERROR
public:
    Storage():arr(new T*[size]){};
    ~Storage()
    {
        for (int i = 0; i < size; i++)
        {
            delete arr[i];
        }
        delete[] arr;
    }
    void push(T obj, int i)
    {
        arr[i] = new T(obj);
    }
    void print()
    {
        for (int i = 0; i < size; i++)
        {
            cout << *arr[i];
        }
        cout << endl;
    }


private:
    T** arr;
};

template <typename T, int size> void Storage<int,size>::print() //LINE 38 ERROR
{
    for (int i = 0; i < size; i++)
        {
            cout << (char) *arr[i];
        }
        cout << endl;
}
#endif /* STORAGE_HPP_ */

И я получаю эту ошибку:

../Storage.hpp:38:63: error: invalid use of incomplete type
class Storage<int, size>
../Storage.hpp:9:1: error: declaration of ‘class Storage<int, size>’

Итак, первый вопрос: можно ли реализовать специальные функции внутри класса?Я пытался, но получил ошибку.Во-вторых, почему я получаю сообщение об ошибке?Спасибо!

РЕДАКТИРОВАТЬ: Я попробовал что-то новое, как кто-то здесь предложил.Я изменил print внутри класса на void print() и реализовал его снаружи, чтобы перегрузить функцию.Вот:

template <typename T, int size>
void Storage<T,size>::print()
{
    for (int i = 0; i < size; i++)
    {
        cout << *arr[i];
    }
    cout << endl;
}


template <typename T, int size>
void Storage<int,size>::print() //ERROR HERE
{
        for (int i = 0; i < size; i++)
        {
            cout << *arr[i];
        }
        cout << endl;
}

Теперь я получаю invalid use of incomplete type ‘class Storage<int, size>’ Где я написал ОШИБКА ЗДЕСЬ (очевидно!) Я понимаю, что это общее решение, я прав?И почему я получаю эту ошибку?

Ответы [ 4 ]

3 голосов
/ 22 сентября 2011

Проблема в том, что вы пытаетесь использовать частичную специализацию всего класса , не имея определенного частично специализированного класса.

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

Это означает, что template <typename T, int n> class Storage<T, n> и template <int n> class Storage<int, n> - это совершенно разные, не связанные классы.Таким образом, вы должны сначала определить последний класс:

template<int n> class Storage<int, n>
{
  // define everything
};

template<int n> void Storage<int, n>::print() { /* implement */ }

Учтите, что частичная специализация Storage<int, n> может быть совершенно другим классом от первичного шаблона и может иметь совершенно другой членфункции.У компилятора нет возможности узнать это, пока вы не определите этот класс.


После комментария sbi вот одна из идей:

//... in the class definition

template<typename S, int m> friend void print_helper(const Storage<S, m> &);
template<int m> friend void print_helper(const Storage<int, m> &);

void print() { print_helper(*this); }

// outside:

template <typename S, int size> void print_helper(const Storage<S, size> & s)
{
  // ...
}
template <int size> void print_helper(const Storage<int, size> & s)
{
  // ...
}

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

0 голосов
/ 23 сентября 2011

Единственная ошибка, которую я вижу, это посторонние typename T в вашей специализации.Должно быть:

template <int size> void Storage<int,size>::print() {...}
0 голосов
/ 22 сентября 2011

Не думаю, что вы можете использовать частичную специализацию для одного метода. Вы можете использовать только полную специализацию.

Вопрос в том, почему вы хотите использовать массив с указанным размером? Почему бы просто не использовать std :: vector и позволить функции push () изменять его размер динамически (с помощью std :: vector :: push_back ())?

0 голосов
/ 22 сентября 2011

Частичные специализации всегда должны использовать полный шаблон, так как они также определяют шаблон.

Так что это не будет работать:

template <int size> void Storage<int,size>::print()

Полные специализации функций-членов могут быть сделаны вне линии для функций-одиночек, потому что они определяют функции.

Так что это будет работать:

template <> void Storage<int,44>::print() 

И вы не можете объявлять / определять какие-либо (частичные) специализации в основном шаблоне.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...