невозможно преобразовать из списка инициализаторов в шаблон <int> - PullRequest
0 голосов
/ 13 января 2020

Это мой класс:

Я перегружаю оператор &&, чтобы определить, имеет ли интервал что-то общее с заданным интервалом, и я пытаюсь сделать исключение, если они не имеют ничего общего, поэтому он вернет интервал с двумя одинаковыми значениями, который должен будет напечатать «EMPTY» в конструкторе, но он не скомпилируется из-за чего-то со списком инициализатора. мой класс: (удалены все нерелевантные функции)

class Interval
{
public:
    friend ostream & operator<<(ostream &output, const Interval<T> & it) {
        if (&it)
            it.print();
        return output;
    }
    friend istream & operator>>(istream &input, Interval<T> & it) {
        it.enter();
        return input;
    }
    Interval();
    Interval(const T &, const T &);
    Interval<T> operator&&(Interval<T> &it);
    Interval<T> operator||(Interval<T> &it);
    ~Interval();
private:
    T a;
    T b;
    int flag;
};

функция перегрузки &&:

template <class T>
Interval<T> Interval<T>::operator&&(Interval<T> &i1) {
    if (b < i1.a)
        return Interval<T>(i1, i1);
    else if (b == i1.a) 
        return Interval<T>(i1, i1);
    else if (a > i1.b) 
        return Interval<T>(i1, i1);
    else if (a == i1.b) 
        return Interval<T>(i1, i1);
    else {
        if (a<i1.a){
            if (b < i1.b)
                return Interval<T>(i1.a, b);
            else return Interval<T>(i1.a, i1.b);
        }
        if (i1.a < a) {
            if (i1.b < b)
                return Interval<T>(a, i1.b);
            else return Interval<T>(a, b);
        }
    }
}

мой конструктор:

Interval<T>::Interval(const T &t1, const T &t2) {
    a = t1;
    b = t2;
    if (t1 == t2) {
        cout << "EMPTY";
    }
    flag = 0;
}

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

Error   C2440   '<function-style-cast>': cannot convert from 'initializer list' to 'Interval<int>'  

что не так с тем, что я сделал?

Ответы [ 2 ]

1 голос
/ 13 января 2020
Error   C2440   '<function-style-cast>': cannot convert from 'initializer list'
                 to 'Interval<int>'

no matching constructor for initialization of 'Interval<int>'
       return Interval<T>(i1, i1);

У вас нет конструктора, принимающего два Interval<T> и i1 равно и Interval<T>. Вам придется создать его, используя два T (* в этом случае int).

Предложение: && обычно используется для логических операций, где результат равен либо true или false. Если вы хотите вернуть a ∩ b (пересечение), я думаю, что T T::operator&(const T2 &b) const; будет более подходящим. Обратите внимание на const: s! Вы не должны изменять какие-либо значения, но возвращаете только что созданный Interval<T>.

Кроме того, if(&it) не требуется. it - это const Interval<T>& (ссылка) - и ссылки всегда должны ссылаться на что-то, следовательно, &it не может вернуть nullptr. Если бы it был бы const Interval<T>* (указатель) с другой стороны, это могло бы быть nullptr, и тогда проверка имела бы смысл. Ссылки хороши в этом смысле!

Еще одно замечание: вам не нужно использовать <T> после Interval внутри определения класса. Interval означает Interval<T> по умолчанию. Только если вы хотите смешать его с другим типом Interval, вам нужно будет указать тип для него. Как в:

template<typename T>
class Interval {
    template<typename U>
    void something(Interval& a, Interval<U>& b) {
        // a is an Interval<T>&
        // b is an Interval<U>&
    }
};

Вам также не нужно делать потоковые операторы friend с, так как они не имеют прямого доступа к private членам. Для этого у вас есть функции-члены print() и enter().

Более подробная информация и предложения с комментариями в коде:

#include <algorithm>  // std::min, std::max
#include <iostream>

// half-open interval:  [a, b)
template<typename T>
class Interval
{
public:
    // default constructs an empty interval
    Interval() : 
        Interval({}, {})  // delegating to the below constructor
    {}

    Interval(const T& t1, const T& t2) : // <- use the member initializer list
        a{t1},
        b{t2},
        flag{0}
    {
        if(b < a) b = a; // illegal, make it empty
        if(a == b) std::cout << "EMPTY\n";
    }

    // itersection
    Interval operator&(const Interval& it) const {
        // Construct the Interval<T> using copy-list-initialization.
        // A return statement with braced-init-list used as the return expression
        // and list-initialization initializes the returned object.

        return  {
                    std::max(a, it.a), // get the greatest lower bound
                    std::min(b, it.b)  // get the smallest upper bound
                };
    }

    std::ostream& print(std::ostream& os) const {        
        return os << '[' << a << ',' << b << ')';
    }

    std::istream& enter(std::istream& is) {        
        return is >> a >> b;
    }

private:
    T a;
    T b;
    int flag;
};

// streaming operators do not need to be friends since they use public member functions
template<typename T>
std::ostream& operator<<(std::ostream& output, const Interval<T>& it) {
    return it.print(output);
}

template<typename T>
std::istream& operator>>(std::istream& input, Interval<T>& it) {
    return it.enter(input);
}

int main() {
    Interval<int> x(0, 10);
    Interval<int> y(5, 15);

    Interval<int> u; // using the new default constructor
    u = x & y;
    std::cout << u << '\n'; // [5,10)

    std::cout << (Interval<int>(0,20) & Interval<int>(5,15)) << '\n'; // [5,15)
    std::cout << (Interval<int>(0,10) & Interval<int>(10,20)) << '\n'; // EMPTY [10,10)
    std::cout << (Interval<int>(100,200) & Interval<int>(0,100)) << '\n'; // EMPTY [100,100)
}
0 голосов
/ 13 января 2020

В вашем коде много ошибок.

Я предполагаю, что у вас template <typename T> над вашим классом, или весь код неверен

Самый важный внутри ваш оператор &&

Вы объявили только один конструктор, который принимает 2 аргумента, оба из которых const T&. Тем не менее, внутри вашей функции-члена вы смешиваете вызовы конструктора либо с

const T&, const T&
const Interval<T>&, const Interval<T>&
const T&, const Interval<T>&
const Interval<T>&, const T&

Некоторые из этих вызовов завершатся неудачно, так как вы предоставили только следующие конструкторы.

Interval();
Interval(const T &, const T &);
// and copy/move constructors, if possible

Существует также проблема с вашим операторы потока, вы берете поток, но вы игнорируете его, вы берете свой аргумент с помощью константной ссылки, но вы проверяете, не является ли он nullptr, ссылки не должны быть "сделаны" из nullptr, это неопределенное поведение.

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

<source>:31:16: error: no matching constructor for initialization of 'Interval<int>'
        return Interval<T>(i1, i1);
               ^           ~~~~~~

<source>:65:7: note: in instantiation of member function 'Interval<int>::operator&&' requested here
    x && y;
...