Шаблон перегруженной функции никогда не вызывается - PullRequest
4 голосов
/ 29 марта 2011

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

Вот что я делаю:

class Terminallog {
public:

    Terminallog();
    Terminallog(int);
    virtual ~Terminallog();

    template <class T>
    Terminallog & operator<<(const T &v);
    template <class T>
    Terminallog & operator<<(const std::vector<T> &v);
    template <class T>
    Terminallog & operator<<(const std::vector<T> *v);
    template <class T, size_t n>
    Terminallog & operator<<(const T(&v)[n]);
    Terminallog & operator<<(std::ostream&(*f)(std::ostream&));
    Terminallog & operator<<(const char v[]);

    //stripped code

};

//stripped code

template <class T>
Terminallog &Terminallog::operator<<(const T &v) {
    if (this->lineendet == true) {
        this->indent();
    }
    this->lineendet = false;
    std::cout << v;
    return *this;
}

template <class T>
Terminallog &Terminallog::operator<<(const std::vector<T> &v) {
    for (unsigned int i = 0; i < v.size(); i++) {
        std::cout << std::endl;
        this->indent();
        std::cout << i << ": " << v.at(i);
    }
    std::cout << std::flush;
    return *this;
}

template <class T>
Terminallog &Terminallog::operator<<(const std::vector<T> *v) {
    for (unsigned int i = 0; i < v->size(); i++) {
        std::cout << std::endl;
        this->indent();
        std::cout << i << ": " << v->at(i);
    }
    std::cout << std::flush;
    return *this;
}

template <class T, size_t n>
Terminallog &Terminallog::operator<<(const T(&v)[n]) {
    unsigned int elements = sizeof (v) / sizeof (v[0]);
    for (unsigned int i = 0; i < elements; i++) {
        std::cout << std::endl;
        this->indent();
        std::cout << i << ": " << v[i];
    }
    std::cout << std::flush;
    return *this;
}

inline
Terminallog &Terminallog::operator<<(std::ostream&(*f)(std::ostream&)) {
    if (f == static_cast<std::ostream & (*)(std::ostream&)> (std::endl)) {
        this->lineendet = true;
    }
    std::cout << f;
    return *this;
}

inline
Terminallog &Terminallog::operator<<(const char v[]) {
    if (this->lineendet == true) {
        std::cout << std::endl;
        this->indent();
        std::cout << v;
    }
    this->lineendet = false;
    std::cout << v;
    return *this;
}

//sripped code

Теперь я пытаюсь что-то вроде

vector<int> *test3 = new vector<int>;
    test3->push_back(1);
    test3->push_back(2);
    test3->push_back(3);
    test3->push_back(4);

Terminallog clog(3);
clog << test3;

, который компилируется просто отлично. Однако, выполняя код, он печатает адрес test3 вместо всех элементов. Я делаю вывод, что компилятор считает, что

Terminallog & operator<<(const T &v);

лучше подходит. Однако я не знаю, что с этим делать. Где ошибка в моем коде? Почему

Terminallog & operator<<(const std::vector<T> *v);

никогда не звонил?

Ответы [ 2 ]

5 голосов
/ 29 марта 2011

Тип test3 в вашем коде std::vector<int> *, но нет Terminallog::operator<<, который принимает аргумент этого типа.Есть один, который берет const std::vector<int> *, и он будет вызван, если вы сделаете

clog << const_cast<const vector<int>*>(test3);

Кстати, создание нового вектора почти никогда не является хорошей идеей.

4 голосов
/ 29 марта 2011

Чтобы соответствовать версии указателя на вектор-констант, к типу необходимо добавить const, а это не const верхнего уровня (const-pointer-to-vector, т.е. std::vector<T>* const). Выбранная перегрузка не требует каких-либо преобразований типов и лучше подходит.

Я бы предложил полностью устранить перегрузку указателя, особенно учитывая, что он просто дублирует перегрузку ссылки на вектор. Вместо этого просто разыменуйте указатель.

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