Nano Hash - криптовалюты, майнинг, программирование

перегрузка оператора ‹‹ шаблоном для изменения вывода

У меня есть класс с именем number, и мне нужна помощь с перегрузкой операторов.

template<class T>
class Number{
public:
    Number(T _numerator,T _denominator){
        numerator = _numerator;
        denominator = _denominator;
    }
    ~Number(){
        ;
    }
    T GetData(){
        return numerator/denominator;
    }
    friend std::ostream &operator<<(std::ostream &out, Number c)     //output
    {
        out << c.numerator/c.denominator;
        return out;
    }
    void SetData(T _numerator,T _denominator){
        numerator = _numerator;
        denominator = _denominator;
    }

private:
    T numerator;
    T denominator;
};

это то, что у меня есть, но я бы хотел, чтобы другой оператор был перегружен, например:

template<class X>
friend std::ostream &operator<<(std::ostream &out, Number c)     //output
{
    out << (X)c.numerator/(X)c.denominator;
    return out;
}

таким образом, я могу вызвать cout следующим образом (я знаю, что могу просто изменить шаблон номера на двойной, но это не то, что я хочу):

Number<int> t(10,23);
std::cout << t<double> << "\n";

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


  • в общем, вы должны использовать операторы приведения C++ вместо оператора приведения в стиле C (). то есть static_cast. 07.12.2013
  • Я только что сделал быстрый поиск в Google, и я думаю, что вы правы. Есть ли какое-то преимущество у гипса в стиле С? 07.12.2013
  • Да, я до сих пор иногда использую приведение в стиле C, когда мне лень. Но я не думаю, что лень — это хорошо. Операторы приведения C++ намного безопаснее. static_cast прежде всего. 07.12.2013
  • Спасибо, что прояснили это для меня. 07.12.2013

Ответы:


1

Я думаю, вы думаете об этом слишком сложно, и то, как вы хотите это использовать, не сработает.

Когда вам нужно, чтобы он был двойным, сделайте его двойным, поэтому я добавил здесь новый член as()

template<class T>
class Number{
public:
    Number(T _numerator,T _denominator){
        numerator = _numerator;
        denominator = _denominator;
    }
    ~Number(){
        ;
    }
    T GetData(){
        return numerator/denominator;
    }
    friend std::ostream &operator<<(std::ostream &out, Number c)     //output
    {
        out << c.numerator/c.denominator;
        return out;
    }
    void SetData(T _numerator,T _denominator){
        numerator = _numerator;
        denominator = _denominator;
    }

    template<typename U>
    Number<U> as(){
        return Number<U>(U(numerator), U(denominator));
    }

private:
    T numerator;
    T denominator;
};


Number<int> t(10,23);
std::cout << t.as<double>() << "\n";
07.12.2013
  • большое спасибо. Я бы предпочел, чтобы был способ использовать мой метод, но не похоже, что это возможно. 07.12.2013

  • 2

    Вы можете приблизиться к тому, что ищете, любым количеством способов. К сожалению, точный синтаксис, который вам нужен, невозможен , так как желаемый тип должен быть закреплен через что-то (будь то функция, сконструированный объект и т. д.).

    Vinzenz показал вам, как вы можете закрепить его через функцию-член. Вот как вы можете закрепить его через альтернативный конструктор.

    #include <iostream>
    
    template<class T>
    class Number
    {
        // allow friending alternate types
        template<typename> friend class Number;
    
        friend std::ostream &operator<<(std::ostream &out, Number c)     //output
        {
            out << c.GetData();
            return out;
        }
    
    public:
        Number(T _numerator = 0, T _denominator = 1)
            : numerator(_numerator)
            , denominator(_denominator)
        {
        }
    
        // constructor for alt-type conversion
        template<typename X>
        Number(const Number<X>& obj)
            : numerator(static_cast<T>(obj.numerator))
            , denominator(static_cast<T>(obj.denominator))
        {
        }
    
        // getter should be const
        T GetData() const
        {
            return numerator/denominator;
        }
    
        void SetData(T _numerator,T _denominator)
        {
            numerator = _numerator;
            denominator = _denominator;
        }
    
    private:
        T numerator;
        T denominator;
    };
    
    int main()
    {
        Number<int> num(10,5);      // regular construction
        Number<float> flt = num;    // alternate type construction
    
        // operator tests
        std::cout << num << '\n';
        std::cout << flt << '\n';
        std::cout << Number<double>(num) << std::endl; // temp construction
    
        return EXIT_SUCCESS;
    }
    

    Вывод

    2
    2
    2
    

    Удачи.

    07.12.2013
    Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

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

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

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

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..