I am in the process of converting a large set of geospatial code from one projection to another. To enforce proper units during this conversion, I have introduced Distance, Point, Rectangle, and Polygon templates which take a tag indicating what coordinate system is used. This is working out fairly well, but there are a lot of places where checks are performed for non-zero (!= 0) or positive values (> 0). I would like to be able to overload these operators to allow comparing against 0 without comparing against any other number. Is it possible to accomplish this?
As an additional restriction, I cannot use constexpr because I must support VS 2013, but I'd still be interested to hear if there is a way to do this with constexpr
Just for reference, I am working with something like this:
template<typename Tag> struct Distance
{
int value;
};
template<typename Tag> struct Point
{
Distance<Tag> x;
Distance<Tag> y;
};
// This works fine for comparing two Distances
template<typename Tag> bool operator>(const Distance<Tag>& a, const Distance<Tag>& b) {return a.value > b.value;}
// But I don't want this to allow a > 14, only a > 0
template<typename Tag> bool operator>(const Distance<Tag>& a, int b) {return a.value > b;}
struct Mercator;
typedef Point<Mercator> MercPoint;
struct GuiScale;
typedef Point<GuiScale> GuiPoint;
// etc.
You may use nullptr_t as a hack (as literal 0 convert to nullptr):
template<typename Tag> bool operator>(const Distance<Tag>& a, std::nullptr_t b) {return a.value > 0;}
You might use the conversion-to-any-pointer of a literal zero:
#include <type_traits>
template<typename Tag>
struct Distance
{
private:
using literal_zero = void(Distance::*)();
template<typename U>
using enable_nullptr = typename std::enable_if<
std::is_same< typename std::decay< U >::type, std::nullptr_t >::value
>::type;
public:
int value;
bool operator<( literal_zero ) const { return value < 0; }
template<typename U>
enable_nullptr<U> operator<( const U& ) const = delete;
};
int main() {
Distance<int> a;
a.value = 0;
a < 0;
// a < 42; // does not compile
// a < nullptr; // does not compile
}
This, unlike the other answer, also disallows a < nullptr. Also, if you remove the nullptr-related part and replace the using literal_zero = ... with a typedef, the same technique works with C++98.
Live example
If it's semantically valid to compare with a literal 0, it's valid to allow a conversion from literal 0 as well. With the conversion in place, you need no special case comparisons (Live at Coliru):
template<typename Tag> struct Distance
{
int value;
Distance() = default;
explicit constexpr Distance(int v) : value(v) {}
constexpr Distance(std::nullptr_t) : value(0) {}
friend constexpr bool operator == (const Distance& lhs, const Distance& rhs) {
return lhs.value == rhs.value;
}
friend constexpr bool operator < (const Distance& lhs, const Distance& rhs) {
return lhs.value < rhs.value;
}
// ...
};
Related
I have encountered this greater<pair<int,int>> in many codes.
For example, in the initialisation of the priority queue [code below]
priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>> pq;
I tried a lot of googling but still couldn't find the best answer.
This is the std::greater type.
This is a function object type that does comparisons using the > operator. A rough implementation looks like this:
template<typename T>
struct greater {
constexpr auto operator()(T const& a, T const& b) const -> bool {
return a > b; // greater operator
}
};
In your example, this is being used to order the std::pairs in the priority_queue from "smallest" to "largest" using std::pair's operator >.
The std::greater is a template function object defined as:
template<typename T> struct greater {
constexpr bool operator()(T const& a, T const& b) const {
return a > b; // greater operator
}
};
Now, the '>' operator is defined for std::pair as -
template <class T1, class T2>
bool operator> (const pair<T1,T2>& lhs, const pair<T1,T2>& rhs) { return rhs<lhs; }
Now, the '<' operator is defined as-
template <class T1, class T2>
bool operator< (const pair<T1,T2>& lhs, const pair<T1,T2>& rhs)
{ return lhs.first<rhs.first || (!(rhs.first<lhs.first) && lhs.second<rhs.second); }
So, effectively, the function greater<pair<int, int>> works as-
template<typename T> struct greater {
constexpr bool operator()(T const& a, T const& b) const {
return a.first>b.first || ( (a.first<b.first) && (a.second>b.second));
}
};
That is, greater<pair<int, int>>(a, b) returns true if and only if the 'first' parameter of a is greater than b or if 'first' parameters are equal then 'second' parameter of a is greater than b.
This is a strict weak ordering.
Is it possible to implement std::optional such that sizeof(std::optional<double>) == 8 by somehow using that you can store characters in a NAN, see http://en.cppreference.com/w/cpp/numeric/math/nan? Are there implementations that do that? Can it be done in terms of the functionality that is available in the standard?
I don't think this can be done because there is no rule preventing programs from utilizing and relying on the extra bits in NaN on their own. Then if you store the magic number into the optional it looks like it's not present instead of the application's special NaN.
Answer is multifold.
First of all, it can not be implemented with the functionality available in Standard, since Standard says nothing of floating point implementation.
Second, for IEEE 754 floating points you can implement your own optional by specializing std::optional for doubles. However, this would mean that you exclude a valid value (NaN is a result produced by some arithmetic operations) from your range of values. However, diving deep into IEEE 754, you might choose a specific NaN representation (there are a lot of those!) as a no-value.
It is not possible to implement std::optional like that because it contradicts the post-conditions that specify how the class (template) behaves. For example: std::optional contains a value if it is initialized with a value of type T, but your suggested std::optional<double> would not contain a value if it was initialized with a value that is the special NaN value that you've chosen.
Also, the C++ standard does not guarantee/require that the floating point type supports (quiet) NaN. Some systems do not.
It is certainly possible to implement your own non-standard optional class with different semantics. Of course, you will then be relying on the implementation defined fact that NaN values exist. You also have to rely on the knowledge of the floating point representation, because as far as I know, there are no standard utilites for inspecting the NaN payload - only for generating a value that has a specific payload.
Implementing what you propose is rather trivial, using a good text editor and cut-and-paste. Since it's a good idea, I've decided to add it to my tool box. My main motivation is that std::optional<>s are rather big, and thus not practical to use in std::variant<> types.
#include <type_traits>
#include <limits>
#include <exception>
class bad_optional_flt_access
: public std::exception
{
public:
bad_optional_flt_access() {}
const char* what() const noexcept override
{
return "bad optional float access";
}
};
template <typename Float, bool = std::is_floating_point<Float>::value>
class optional_flt;
template <typename Float>
class optional_flt<Float, false> {};
template <typename Float>
class optional_flt<Float, true>
{
public:
constexpr optional_flt() noexcept : value_(std::numeric_limits<Float>::quiet_NAN()) {}
constexpr optional_flt(const Float& val) noexcept : value_(val) {}
template<typename T>
constexpr optional_flt(const T& val) noexcept : value_(Float(val)) {}
constexpr bool has_value() const noexcept
{
return value_ != std::numeric_limits<Float>::quiet_NAN();
}
void reset() noexcept { value_ = std::numeric_limits<Float>::quiet_NAN(); }
constexpr void swap(optional_flt& other) noexcept { std::swap(value_, other.value_); }
constexpr operator bool() const noexcept { return has_value(); }
Float& value () &
{
if (!has_value())
throw bad_optional_flt_access();
return value_;
}
Float&& value () &&
{
if (!has_value())
throw bad_optional_flt_access();
return value_;
}
constexpr const Float& value () const &
{
if (!has_value())
throw bad_optional_flt_access();
return value_;
}
Float& operator * () & noexcept { return value_; }
constexpr const Float& operator * () const & noexcept{ return value_; }
template< class U >
constexpr Float value_or( U&& default_value ) const&
{
return (has_value()) ? value_ : default_value;
}
template< class U >
constexpr Float value_or( U&& default_value ) &&
{
return (has_value()) ? value_ : default_value;
}
private:
Float value_;
};
template< class T, class U >
constexpr bool operator==( const optional_flt<T>& lhs, const optional_flt<U>& rhs )
{
return lhs.value() == rhs.value();
}
template< class T, class U >
constexpr bool operator!=( const optional_flt<T>& lhs, const optional_flt<U>& rhs )
{
return lhs.value() != rhs.value();
}
template< class T, class U >
constexpr bool operator<( const optional_flt<T>& lhs, const optional_flt<U>& rhs )
{
return lhs.value() < rhs.value();
}
template< class T, class U >
constexpr bool operator<=( const optional_flt<T>& lhs, const optional_flt<U>& rhs )
{
return lhs.value() <= rhs.value();
}
template< class T, class U >
constexpr bool operator>( const optional_flt<T>& lhs, const optional_flt<U>& rhs )
{
return lhs.value() > rhs.value();
}
template< class T, class U >
constexpr bool operator>=( const optional_flt<T>& lhs, const optional_flt<U>& rhs )
{
return lhs.value() >= rhs.value();
}
template<typename T>
constexpr optional_flt<T> make_optional_flt(const T& x)
{
return optional_flt<T>(x);
}
int main()
{
int i = 2;
auto x = optional_flt<float>{i};
auto y = optional_flt<double>(2.5);
return (*x < .5) ? sizeof(optional_flt<double>) : 1;
}
The code above is gcc -std=c++11, clang -std=c++14, and cl /std:c++11 compatible.
I have the following boost::variant type
using MyType = boost::variant<int, double, char, std::string, bool>;
and I would like to be able to use this type in as natural way as possible, in particular I'd like to be able to use the comparison operators such that comparison of types that would compile, give then correct result, otherwise behaviour is undefined (or an exception is thrown). For example suppose I have
MyType x {2}; // int
MyType y {1.0}; // double
MyType z {"hello"}; // std::string
I'd like to be able to compare x with y in the same way as comparing int {2} and double {1.0}. boost::variant already defined operator< etc, so I can make this comparison, but the result is not as expected.
cout << (x < y) << endl; // 1
cout << (y < x) << endl; // 0
I can define the desired behaviour using a boost::static_visitor
template <typename T, typename U, typename R = MyType>
using enable_if_both_arithmetic = std::enable_if_t<std::is_arithmetic<T>::value && std::is_arithmetic<U>::value, R>;
template <typename T, typename U, typename R = MyType>
using enable_if_not_both_arithmetic = std::enable_if_t<!(std::is_arithmetic<T>::value && std::is_arithmetic<U>::value), R>;
class is_less_than : public boost::static_visitor<bool>
{
public:
template <typename T>
bool operator()(const T& lhs, const T& rhs) const
{
return lhs < rhs;
}
template <typename T, typename U>
enable_if_both_arithmetic<T, U, bool> operator()(const T& lhs, const U& rhs) const
{
return lhs < rhs;
}
template <typename T, typename U>
enable_if_not_both_arithmetic<T, U, bool> operator()(const T& lhs, const U& rhs) const
{
return false; // or could throw
}
};
Which can be used like
cout << boost::apply_visitor(is_less_than(), x, y) << endl; // 0
but this is long and ugly. Is there someway I can 'overwrite' the boost::variant::operator< and use my own?
bool operator<(const VcfType& lhs, const VcfType& rhs)
{
return boost::apply_visitor(is_less_than(), lhs, rhs);
}
You are allowed to define a subclass containing the operator< you need, either of the boost::variant<int, double, char, std::string, bool> template instantiation (probably simpler) or of the boost::variant<> template (if you have other cases to cover).
How can I make it so that (with objects of different template types) A*B and B*A give the same result, where the type of the result is determined according to the usual C++ type promotion rules?
For example:
int main()
{
number<float> A(2.0f);
number<double> B(3.0);
A*B; // I want 6.0 (double)
B*A; // I want 6.0 (double)
return 0;
}
At the moment, I can only multiply objects of the same template type. For example, something like this:
template<typename T>
class number
{
public:
number(T v) : _value(v) {}
T get_value() const { return _value; }
number& operator*=(const number& rhs)
{
_value *= rhs.get_value();
return *this;
}
private:
T _value;
};
template<typename T>
inline number<T> operator*(number<T> lhs, const number<T>& rhs)
{
lhs *= rhs;
return lhs;
}
EDIT: Or, as in the answers, I can multiply objects of different template types, but always returning the same type as lhs. Is there any way to instead return an object whose type is determined by the standard type promotion rules?
EDIT 2: I would like to avoid C++11 features if possible.
You have to templatize e.g. the rhsparameters:
template<typename T>
class number
{
public:
number(T v) : _value(v) {}
T get_value() const { return _value; }
template<class E>
number& operator*=(const number<E>& rhs)
{
_value *= rhs.get_value();
return *this;
}
private:
T _value;
};
template<class T, class E, class RET = decltype(T()*E())>
number<RET> operator*(number<T>& lhs, const number<E>& rhs)
{
return lhs.get_value()*rhs.get_value();
}
You can use std::common_type<> to obtain the type required for the return. For example
template<typename X>
struct number
{
// ...
template<typename Y>
number(number<Y> const&other); // needed in line 1 below
template<typename Y>
number&operator=(number<Y> const&other); // you may also want this
template<typename Y>
number&operator*=(number<Y> const&other); // needed in line 2 below
template<typename Y>
number<typename std::common_type<X,Y>::type> operator*(number<Y> const&y) const
{
number<typename std::common_type<X,Y>::type> result=x; // 1
return result*=y; // 2
}
};
I left out the implementations of the templated constructor and operator*=.
Unfortunately, std::common_type is C++11, which you want to avoid for obscure reasons. If you only work with built-in types (double, float, int, etc), you can easily implement your own version of common_type. However, if you want to do sophisticated meta-template programming, it is strongly recommended to move on to C++11 – it's already 4 years old and mostly backwards compatible.
You need a templated overload for the operator*()
template<typename T>
class number {
public:
// ...
template<typename U>
number& operator*=(const number<U>& rhs) {
// ...
}
// ...
};
And the same for the binary operator
template<typename T,typename U>
inline number<T> operator*(number<T> lhs, const number<U>& rhs) {
lhs *= rhs;
return lhs;
}
I got this n-dimensional point object:
template <class T, unsigned int dimension> class Obj {
protected:
T coords[dimension];
static const unsigned int size = dimension;
public:
Obj() { };
Obj(T def) { for (unsigned int i = 0; i < size; ++i) coords[i]=def; };
Obj(const Obj& o) { for (unsigned int i = 0; i < size; ++i) coords[i] = o.coords[i]; }
const Obj& operator= (const Obj& rhs) { if (this != &rhs) for (unsigned int i = 0; i < size; ++i) coords[i] = rhs.coords[i]; return *this; }
virtual ~Obj() { };
T get (unsigned int id) { if (id >= size) throw std::out_of_range("out of range"); return coords[id]; }
void set (unsigned int id, T t) { if (id >= size) throw std::out_of_range("out of range"); coords[id] = t; }
};
and a 3D point class which uses Obj as base class:
template <class U> class Point3DBase : public Obj<U,3> {
typedef U type;
public:
U &x, &y, &z;
public:
Point3DBase() : x(Obj<U,3>::coords[0]), y(Obj<U,3>::coords[1]), z(Obj<U,3>::coords[2]) { };
Point3DBase(U def) : Obj<U,3>(def), x(Obj<U,3>::coords[0]), y(Obj<U,3>::coords[1]), z(Obj<U,3>::coords[2]) { };
Point3DBase(U x_, U y_, U z_) : x(Obj<U,3>::coords[0]), y(Obj<U,3>::coords[1]), z(Obj<U,3>::coords[2]) { x = x_; y = y_; z= z_; };
Point3DBase(const Point3DBase& other) : x(Obj<U,3>::coords[0]), y(Obj<U,3>::coords[1]), z(Obj<U,3>::coords[2]) { x = other.x; y = other.y; z = other.z; }
// several operators ...
};
The operators, basically the ones for comparison, use the simple compare-the-member-object approach like:
friend bool operator== (const Point3DBase<U> &lhs, const Point3DBase<U> rhs) { return (lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z); }
Then it occured to me that for the comparion of double values the simply equality approach is not very useful since double values should be compared with an error margin. What would be the best approach to introduce an error margin into the point? I thought about an epsDouble type as template parameter but I can't figure out how to achieve this.
edit:
I've seen chained output stream operators that call the output stream operator of the type of the output stream operator ... Is there a way to delegate the comparison to a custom type that represents a float point type?
If you want one epsilon value for all instances of a given floating type, it's actually quite simple:
template <>
bool operator<(const Point3DBase<double>& lhs, const Point3DBase<double>& rhs)
{
}
If not, then I shall orient you toward Policy-based Design as Alexandrescu showed:
namespace detail
{
template <class U>
struct DefaultComparator: std::binary_function<bool, U, U>
{
bool operator()(U lhs, U rhs) const { return lhs < rhs; }
};
}
template < class U, class Comparator = detail::DefaultComparator<U> >
class Point3DBase;
template < class U, class C>
bool operator<(Point3DBase<U,C> const& lhs, Point3DBase<U,C> const& rhs)
{
return C()(lhs,rhs);
}
Note that you can still define a safe default by specializing DefaultComparator
namespace detail
{
template <>
struct DefaultComparator<float> {};
template <>
struct DefaultComparator<double> {};
}
With this definition, it is not possible to use operator== without passing a Comparator parameter oneself. Another solution would be to allow it but provide a default epsilon in the definition of the two specialization above.
All other operations (>, <=, >=, ==, !=) can be trivially derived (though perhaps not efficiently) from <, for example by deriving from boost::equality_comparable and/or boost::less_than_comparable.
Yeah, you can't have a template parameter of a floating point type. You could have an int parameter instead, telling the negative 10 base log of the epsilon value, e.g. a value of 3 would mean 0.001 .
If you want to master the epsilon you can define a wrapper class of double that takes care of the this epsilon when comparing instances of this class. In this way you are able to use whatever other functions or classes that are templated on the numeric type.
template <int EPS>
class DoubleEps {
double val;
public:
operator double {return val;}
DoubleEps(double d) : val(d) {}
operator==(DoubleEps d) {
// take care of epsilon
}
// other operators if needed
};