Я работаю с набором классов, и мой основной код выглядит следующим образом:
main.cpp
#include "calc.h"
int main() {
neg_inf nif;
pos_inf pif;
limit<double, infinity> l( 3.4, nif, pif, 2.2 )
std::cout << "value dx = " << l.value() << '\n'
<< "lower lim = " << l.lower() << '\n'
<< "upper lim = " << l.upper() << '\n'
<< "step_size = " << l.step() << '\n';
return EXIT_SUCCESS;
}
Ожидаемый результат должен быть:
value dx = 3.4
lower lim = -inf
upper lim = inf
step_size = 2.2
Вот мои уроки:
calc.h
#pragma once
#include <cmath>
#include <iostream>
#include <limits>
#include <type_traits>
struct infinity {
protected:
infinity() = default;
};
struct pos_inf : public infinity {
constexpr double operator()() { return std::numeric_limits<double>::infinity(); }
};
struct neg_inf : public infinity {
constexpr double operator()() { return -std::numeric_limits<double>::infinity(); }
};
std::ostream& operator<<( std::ostream& os, const pos_inf& inf );
std::ostream& operator<<( std::ostream& os, const neg_inf& inf );
template<typename dX, class bound>
class limit {
dX dx;
bound lowerBound;
bound upperBound;
double step_size;
public:
limit( dX x, bound lower, bound upper, double step = 1 ) :
dx{ x }, lowerBound{ lower }, upperBound { upper }, step_size { step }
{}
dX value() const { return dx; }
bound lower() const { return lowerBound; }
bound upper() const { return upperBound; }
double step() const { return step_size; }
};
calc.cpp
#include "calc.h"
std::ostream& operator<<( std::ostream& os, const pos_inf& inf ) {
// originally intended to do:
// return os << inf(); // but fails to compile
auto v = pos_inf()(); // this works
return os << v;
}
std::ostream& operator<<( std::ostream& os, const neg_inf& inf ) {
// same as above...
auto v = neg_inf()();
return os << v;
}
Однако в main.cpp Visual Studio 2017 генерирует эту ошибку компилятора:
c:\***\main.cpp(33): error C2679: binary '<<': no operator found which takes a right-hand operand of type 'bound' (or there is no acceptable conversion)
1> with
1> [
1> bound=infinity
1> ]
на основе этой строки кода:
<< "lower lim = " << l.lower() << '\n'
и не может выполнитьl.lower()
Однако, если я делаю это в основном:
#include "calc.h"
int main() {
neg_inf nif;
pos_inf pif;
std::cout << nif << '\n' << pif << '\n'
return EXIT_SUCCESS;
}
Я получаю вывод:
-inf
inf
Это говорит мне, что мои operator<<()
работая для унаследованных структур, однако, когда я передаю его родительский тип в качестве аргумента шаблона и передаю производные типы в конструктор моего limit
класса, operator<<()
не разрешаются.Кажется, это проблема двусмысленности, но я не уверен, как решить эту проблему.Что я здесь упускаю или пропускаю?
Как примечание, которое выходит за рамки этого вопроса, есть ли более элегантный способ изобразить -/+inf
?Я использую здесь наследование, потому что +
и -
inf
не числа, а скорее понятие, они похожи друг на друга, но указывают в разных направлениях.Поэтому, когда я передаю бесконечный тип в качестве аргумента шаблона, я хотел бы иметь возможность установить нижнюю границу на -inf, а верхнюю границу на + inf.Я хочу, чтобы связанный тип был шаблоном, потому что я мог бы использовать целочисленные или двойные границы, например, между [-1,1]
или [0.0,1.0]
, в которых все это числовые границы.Я не уверен, как еще выразить бесконечность более изящным способом, и любые советы или предложения будут оценены.