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)
}