Функция, которая печатает что-то к станд.:: ostream и станд. возвратов:: ostream?

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

Мы используем в несколько измененной форме, передавая подкласс в, черты вводят структуру к суперклассу для позволения суперклассу к эхо-сигналам производного типа. Приложение является библиотекой для геометрического исчисления (точки, векторы, строки, поля), где вся универсальная функциональность реализована в суперклассе, и подкласс просто определяет определенный тип: CFltPoint наследовался TGenPoint. Также CFltPoint существовал перед TGenPoint, таким образом разделяя на подклассы был естественный способ осуществить рефакторинг это.

8
задан Jon Seigel 8 April 2010 в 03:04
поделиться

7 ответов

Вы не можете исправить эту функцию. Ничто в спецификации не требует, чтобы компилятор оценивал вызов функции в выражении в каком-либо определенном порядке относительно какого-либо несвязанного оператора в том же выражении. Таким образом, без изменения вызывающего кода вы не можете заставить MyPrint () выполнить оценку после std :: cout << "Value:"

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

Вы не можете добиться того же с бесплатными вызовами функций, потому что они нет LHS. MyPrint () возвращает объект, равный std :: cout , как и std :: cout << "Value:" , поэтому вы фактически выполняете std :: cout << std :: cout , который печатает это шестнадцатеричное значение.

Поскольку желаемый результат:

Value: 12

"правильным" является переопределение оператора <<. Это часто означает, что вам нужно либо сделать его другом, либо сделать следующее:

class WhateverItIsYouReallyWantToPrint {
    public:
    void print(ostream &out) const {
        // do whatever
    }
};

ostream &operator<<(ostream &out, const WhateverItIsYouReallyWantToPrint &obj) {
    obj.print(out);
}

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

, поэтому вы эффективно выполняете std :: cout << std :: cout , который печатает это шестнадцатеричное значение.

Поскольку желаемый результат:

Value: 12

"правильный" действительно нужно переопределить оператор <<. Это часто означает, что вам нужно либо сделать его другом, либо сделать следующее:

class WhateverItIsYouReallyWantToPrint {
    public:
    void print(ostream &out) const {
        // do whatever
    }
};

ostream &operator<<(ostream &out, const WhateverItIsYouReallyWantToPrint &obj) {
    obj.print(out);
}

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

, поэтому вы эффективно выполняете std :: cout << std :: cout , который печатает это шестнадцатеричное значение.

Поскольку желаемый результат:

Value: 12

"правильный" действительно нужно переопределить оператор <<. Это часто означает, что вам нужно либо сделать его другом, либо сделать следующее:

class WhateverItIsYouReallyWantToPrint {
    public:
    void print(ostream &out) const {
        // do whatever
    }
};

ostream &operator<<(ostream &out, const WhateverItIsYouReallyWantToPrint &obj) {
    obj.print(out);
}

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

который выводит это шестнадцатеричное значение.

Поскольку желаемый результат:

Value: 12

«правильным» является переопределение оператора <<. Это часто означает, что вам нужно либо сделать его другом, либо сделать следующее:

class WhateverItIsYouReallyWantToPrint {
    public:
    void print(ostream &out) const {
        // do whatever
    }
};

ostream &operator<<(ostream &out, const WhateverItIsYouReallyWantToPrint &obj) {
    obj.print(out);
}

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

который выводит это шестнадцатеричное значение.

Поскольку желаемый результат:

Value: 12

«правильным» является переопределение оператора <<. Это часто означает, что вам нужно либо сделать его другом, либо сделать следующее:

class WhateverItIsYouReallyWantToPrint {
    public:
    void print(ostream &out) const {
        // do whatever
    }
};

ostream &operator<<(ostream &out, const WhateverItIsYouReallyWantToPrint &obj) {
    obj.print(out);
}

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

11
ответ дан 5 December 2019 в 08:00
поделиться

There's no way to do what you're expecting there because of the order the functions are evaluated in.

Is there any particular reason you need to write directly to the ostream like that? If not, just have MyPrint return a string. If you want to use a stream inside MyPrint to generate the output, just use a strstream and return the result.

1
ответ дан 5 December 2019 в 08:00
поделиться

У вас есть два варианта. Первый, используя то, что у вас уже есть:

std::cout << "Value: ";
MyPrint(12, &std::cout);
std::cout << std::endl;

Другой, который больше похож на C ++, заключается в замене MyPrint () соответствующим std :: ostream & operator << . Уже есть один для int , поэтому я сделаю его чуть более сложным:

#include <iostream>

struct X {
    int y;
};

// I'm not bothering passing X as a reference, because it's a
// small object
std::ostream& operator<<(std::ostream& os, const X x)
{
    return os << x.y;
}

int main()
{
    X x;
    x.y = 5;
    std::cout << x << std::endl;
}
4
ответ дан 5 December 2019 в 08:00
поделиться

Вы хотите сделать MyPrint классом с оператором друга <<:

class MyPrint
{
public:
    MyPrint(int val) : val_(val) {}
    friend std::ostream& operator<<(std::ostream& os, const MyPrint& mp) 
    {
        os << mp.val_;
        return os;
    }
private:
    int val_;
};

int main(int argc, char** argv)
{
    std::cout << "Value: " << MyPrint(12) << std::endl;
    return 0;
}

Этот метод требует, чтобы вы вставили объект MyPrint в поток по вашему выбору. Если вам ДЕЙСТВИТЕЛЬНО нужна возможность изменить активный поток, вы можете сделать это:

class MyPrint
{
public:
    MyPrint(int val, std::ostream& os) : val_(val), os_(os) {}
    friend std::ostream& operator<<(std::ostream& dummy, const MyPrint& mp) 
    {
        mp.os_ << mp.val_;
        return os_;
    }
private:
    int val_;
    std::ostream& os_
};

int main(int argc, char** argv)
{
    std::cout << "Value: " << MyPrint(12, std::cout) << std::endl;
    return 0;
}
6
ответ дан 5 December 2019 в 08:00
поделиться

Во-первых, нет причин не передавать ostream по ссылке, а не по указателю:

std::ostream& MyPrint(int val, std::ostream& out) {
  out << val;
  return out;
}

Если вы действительно не хотите использовать ] std :: ostream & operator << (std :: ostream & os, TYPE) , вы можете сделать это:

int main(int argc, char** argv){
    std::cout << "Value: ";
    MyPrint(12, std::cout) << std::endl;
    return 0;
}
0
ответ дан 5 December 2019 в 08:00
поделиться

После изменения указателя на ссылку вы можете сделать следующее:

#include <iostream>

std::ostream& MyPrint(int val, std::ostream& out) {
    out << val;
    return out;
}

int main(int, char**) {
    MyPrint(11, std::cout << "Value: ") << std::endl; 

    return 0;
}

Синтаксис для MyPrint по существу аналогичен синтаксису развернутого оператора << , но с дополнительным аргументом.

0
ответ дан 5 December 2019 в 08:00
поделиться

В вашем случае ответ очевиден:

 std::cout << "Value: " << 12 << std::endl;

Если этого недостаточно, объясните, какой результат вы хотите увидеть.

-1
ответ дан 5 December 2019 в 08:00
поделиться
Другие вопросы по тегам:

Похожие вопросы: