There is a popular idiom using std::tie to implement comparison operators:
// foo.h
struct Foo {
int a, b;
string c;
bool operator<(const Foo& rhs) const;
};
// foo.cc
bool Foo::operator<(const Foo& rhs) const {
return tie(a, b, c) < tie(rhs.a, rhs.b, rhs.c);
}
E.g. it's widely used in Chromium
However it requires copying the list of members, so why not write a helper function:
static auto MakeTie(const Foo& x) {
return tie(x.a, x.b, x.c);
}
bool Foo::operator<(const Foo& rhs) const {
return MakeTie(*this) < MakeTie(rhs);
}
// or, in foo.h
auto MakeTie() const;
// and in foo.cc
auto Foo::MakeTie() const { ... }
(btw such member function cannot be called from any other translation unit)
So, why do I see hundreds of such tie(a, b, c) < tie(copy-pasta) pairs, is there a reason behind this?
Firstly, if your class has so many members that doubling up tie is problematic, then you may have a design smell anyway.
I would tend to agree that this is a bit of an annoyance, but remember that it's not the reason for tie's being. There is no such thing as "a tie"; "tie" here is a verb, a way to describe how expressions are being "tied together" into what is actually a tuple of references.
You can of course write your own replacement for tie that knows how all the relevant members of your class, so that this does not need writing out twice. You could call it members_as_tuple. It's up to you as to whether you want to do that, just as it is up to you whether to make any function to avoid some particular duplicated code.
Certainly, though, without reflection, C++ cannot do this for you in the general case, so that's why such a facility isn't provided out of the box.
tl;dr: You've already shown the best (only?) way to do it, but I wouldn't call it make_tie.
As for why people aren't doing this more, well, that's unanswerable. They probably just didn't think of it, or didn't think they needed it, and were probably right.
Related
I want to write a template function that receives parameter by move or by copy.
The most efficient way that I use is:
void setA(A a)
{
m_a = std::move(a);
}
Here, when we use is
A a;
setA(a); // <<---- one copy ctor & one move ctor
setA(std::move(a)); // <<---- two move ctors
I recently found out that defining it this way, with two functions:
void setA(A&& a)
{
m_a = std::move(a);
}
void setA(const A& a)
{
m_a = a; // of course we can so "m_a = std::move(a);" too, since it will do nothing
}
Will save a lot!
A a;
setA(a); // <<---- one copy ctor
setA(std::move(a)); // <<---- one move ctor
This is great! for one parameter... what is the best way to create a function with 10 parameters?!
void setAAndBAndCAndDAndEAndF...()
Any one has any ideas?
Thanks!
The two setter versions setA(A&& a) and setA(const A& a) can be combined into a single one using a forwarding reference (a.k.a. perfect forwarding):
template<typename A>
void setA(A&& a)
{
m_a = std::forward<A>(a);
}
The compiler will then synthesize either the rvalue- or lvalue-reference version as needed depending on the value category.
This also solves the issue of multi-value setters, as the right one will be synthesized depending on the value category of each parameter.
Having said that, keep in mind that setters are just regular functions; the object is technically already constructed by the time any setter can be called. In case of setA, if A has a non-trivial constructor, then an instance m_a would already have been (default-)constructed and setA would actually have to overwrite it.
That's why in modern C++, the focus is often not so much on move- vs. copy-, but on in-place construction vs. move/copy.
For example:
struct A {
A(int x) : m_x(x) {}
int m_x;
};
struct B {
template<typename T>
B(T&& a) : m_a(std::forward<T>(a)) {}
A m_a;
};
int main() {
B b{ 1 }; // zero copies/moves
}
The standard library also often offers "emplace"-style calls in addition to more traditional "push"/"add"-style calls. For example, vector::emplace takes the arguments needed to construct an element, and constructs one inside the vector, without having to copy or move anything.
The best would be to construct a in-place within the constructor. About setters, there is no single best. Taking by value and moving seems to work fine in most cases, but can sometimes be less efficient. Overloading as you showed is maximally efficient, but causes lots of code duplication. templates can avoid code duplication with the help of universal-references, but then you have to roll out your own type checking and it gets complicated. Unless you've detected this as a bottleneck with a profiler, I suggest you stick with take-by-value-then-move as it's the simplest, causes minimal code duplication and provides good exception-safety.
After a lot of research, I have found an answer!
I made an efficient wrapper class that allows you to hold both options and lets you decide in the inner function whether you want to copy or not!
#pragma pack(push, 1)
template<class T>
class CopyOrMove{
public:
CopyOrMove(T&&t):m_move(&t),m_isMove(true){}
CopyOrMove(const T&t):m_reference(&t),m_isMove(false){}
bool hasInstance()const{ return m_isMove; }
const T& getConstReference() const {
return *m_reference;
}
T extract() && {
if (hasInstance())
return std::move(*m_move);
else
return *m_reference;
}
void fastExtract(T* out) && {
if (hasInstance())
*out = std::move(*m_move);
else
*out = *m_reference;
}
private:
union
{
T* m_move;
const T* m_reference;
};
bool m_isMove;
};
#pragma pack(pop)
Now you can have the function:
void setAAndBAndCAndDAndEAndF(CopyOrMove<A> a, CopyOrMove<B> b, CopyOrMove<C> c, CopyOrMove<D> d, CopyOrMove<E> e, CopyOrMove<F> f)
With zero code duplication! And no redundant copy or move!
Short answer:
It's a compromise between verbosity and speed. Speed is not everything.
defining it this way, with two functions ... Will save a lot!
It will save a single move-assignment, which often isn't a lot.
Unless you need this specific piece of code to be as fast as possible (e.g. you're writing a custom container), I'd prefer passing by value because it's less verbose.
Other possible approaches are:
Using a forwarding reference, as suggested in the other answers. It'll give you the same amount of copies/moves as a pair of overloads (const T & + T &&), but it makes passing more than one parameter easier, because you only have to write a single function instead of 2N of them.
Making the setter behave like emplace(). This will give you no performance benefit (because you're assigning to an existing object instead of creating a new one), so it doesn't make much sense.
I want to declare a multiset of a structure.
The current form of my declaration of multiset is
struct obj
{
//code
};
struct compare
{
inline bool operator()(const obj &a, const obj &b)
{
//code
}
};
multiset<obj,compare> mst;
Is there any other form of declaration which may use only one structre by overloading operator for obj.
Yes, you can overload operator < for your struct, either as a member function or as a free-standing one. This will make code more concise (in my purely subjective opinion), but in practice would not lead to any difference in performance.
As a matter of fact, optimizing compiler is more than likely to generate exactly the same code (provided the actual comparison code is the same).
I'm trying to build a Graph Datastructure based on an already existing Datastructure (which I cannot modify and which is not a graph itself).
I think I have somewhat a grasp on how to build most of the structure concerning the graph itself, but right now I have to reference back to the original data structure for one little "compare" function and having a really hard time how to model that properly...
My vertices represent two different classes A and B of the original data structure, that have different member variables and no common ancestors. For an algorithm I have to check whether two vertices are compatible.
The rule is: an A-Vertex and an B-Vertex are always incompatible, but if both vertices represent the same type I have to check some specifics for the respective type.
So the base idea is roughly like this:
bool isCompatible(const Vertex& other){
// if this->data is of other type than other->data
// return false;
// else return compareFunction(this->data, other->data)
// where maybe one could overload that compare-function
// or make a template out of it
}
But I don't really know how to store the reference to data without making it really ugly.
Idea 1) Use a void pointer for data, have some variable to store the type and then cast the void pointer into respective type
-> would probably work but seems really dangerous (type-safety?) and really ugly (basically no reusability for the Graph structure if you ever wanna use it on other data). Seems a bit like the brute force approach.
Idea 2) Make an abstract data class that offers some "isCompatible(data)" function, and have wrapper-classes for A and B respectively that inherit from the abstract class and override that function. Inside the overridden function one could use dynamic_cast then and compare the objects.
-> still doesn't seem like good design, but should also work?
Idea 3) Make templates work? It's my first time working with C++ so I'm having a few problems wrapping my head around that properly.
I think something like the following should work for comparing:
template<typename T1, typename T2>
bool compare(T1 object1, T2 object2){
return false;
}
And then having instances for (A,A) and (B,B) that override this. For me this seems like the way to got for the comparison itself. But I don't really know how to manage the reference from Vertex to the Object without losing the Type. Any suggestions?
I'm open to any other suggestions as well of course.
edit: I'm using C++11 if that's of relevance.
If your data is either an A or a B, where those two types have nothing in common, then sounds like what you want is a variant data type. The C++ standard library doesn't have one yet, but you could use Boost's:
boost::variant<A, B> data;
A variant gives you type safety (which void* doesn't) and doesn't require you to have a common ancestor between the two types (which apparently are conceptually unrelated).
With a variant like the above, you can implement your comparison using binary visitation:
bool isCompatible(const Vertex& other) {
boost::apply_visitor(is_compatible(), data, other.data);
}
with:
class is_compatible
: public boost::static_visitor<bool>
{
public:
template <typename T, typename U>
bool operator()( const T &, const U & ) const
{
return false; // cannot compare different types
}
bool operator()( const A& lhs, const A& rhs ) const
{
// whatever A-specific comparison
}
bool operator()( const B& lhs, const B& rhs ) const
{
// whatever B-specific comparison
}
};
What is the difference between these two ways of overloading the != operator below. Which is consider better?
Class Test
{
...//
private:
int iTest
public:
BOOL operator==(const &Test test) const;
BOOL operator!=(const &Test test) const;
}
BOOL operator==(const &Test test) const
{
return (iTest == test.iTest);
}
//overload function 1
BOOL Test::operator!=(const &Test test) const
{
return !operator==(test);
}
//overload function 2
BOOL Test::operator!=(const &Test test) const
{
return (iTest != test.iTest);
}
I've just recently seen function 1's syntax for calling a sibling operator function and wonder if writing it that way provides any benefits.
Your first overload ensures that calling != on your type will always provide the opposite of calling == even if your implementation of == would change.
Your second overloaded function does not, since it is possible to provide any implementation for == and change the existing implementation in the future.
If you want to ensure that != will always be the opposite of ==, go with the first (at the cost of an extra function call which may very well become inlined anyway).
Here is a good example. Suppose that you have a class Point2D with fields x and y. If you want to implement ==, you will have to compare on field x and on field y. If you implement != by calling operator==, you have shorter code, and will have one function less to change if you ever moved to a polar representation.
Equality tests and comparisons are always susceptible to maintenance errors as the class fields change. Minimizing the number of methods that directly access state can reduce the risk of errors.
They will almost certainly compile to the same machine code.
I prefer choice 2, just because I find it awkward to say "operator==". But you could have used
return ! (*this == test)
And IMHO that's also clear and easy to understand.
I can think of many reasons (or perhaps aspects of the same reason) to write it that way. What they all boil down to is: it's DRY.
It ensures that two objects are always either == or !=
If you decide to change what's in the class, or what's used for equality testing, you only have to change it in one place
I think that conceptually, you really have two different things you're defining here:
A definition of "equality" for class Test
A useful interface by which people using this class can determine equality of their instances
With method 2, you're doing both ad-hoc. With method 1, you're defining equality in operator==, and providing the rest of the interface via operator!=.
Some languages/libraries take it even further, e.g., in Ruby you can define just <=> to compare ordered objects and mix-in Comparable and get equality, inequalities, and between?.
Version #1, while syntacticly ugly IMHO, allows you to change the equality logic in a single place (in the == operator overload). It guarantees the two overloads are always in sync.
In general, the following statement:
return !(*this == object);
allows you to define != in terms of one function. In the world of inheritance, child objects would only need to define operator== in order to use the base class operator!=:
struct Base
{
virtual bool isEqual(const Base& other) const = 0;
bool operator==(const Base& other) const
{
return isEqual(other);
}
bool operator!=(const Base& other) const
{
return !(*this == other); // Uses Base::operator==
}
};
With the above base class, defining operator!= using != would require descendants to implement more methods.
Also, !(*this == other) allows one to define a global, generic function for !=:
template <typename T>
bool operator!=(const T& a, const T& b)
{
return !(a == b);
}
Although this pattern doesn't provide much for == and !=, the differences are larger when using the relational operators: <, <=, >, >=.
In general, it is always better to implement related functionality in terms of each other. In case of operators, there are always groups. For example, != can be implemented in terms of ==; post-increment can be implemented in terms of pre-increment; >, <= and >= can be implemented in terms of < (see std::rel_ops in <utility>) etc. If something about the class needs changing, you only need to modify the core operators, and all the rest will automatically be updated to reflect the new behavior.
The general implementation of all the "secondary" operators is always the same, and so there is even a library which automatically provides operators that are defined in terms of a few provided ones. See Boost.Operators
Your example:
#include <boost/operators.hpp>
class Test : boost::equality_comparable<Test, Test>
{
private:
int iTest;
public:
bool operator==(const Test& test) const;
//look, no operator !=
};
int main()
{
Test a, b;
a != b; //still works
}
I have a function that processes a given vector, but may also create such a vector itself if it is not given.
I see two design choices for such a case, where a function parameter is optional:
Make it a pointer and make it NULL by default:
void foo(int i, std::vector<int>* optional = NULL) {
if(optional == NULL){
optional = new std::vector<int>();
// fill vector with data
}
// process vector
}
Or have two functions with an overloaded name, one of which leaves out the argument:
void foo(int i) {
std::vector<int> vec;
// fill vec with data
foo(i, vec);
}
void foo(int i, const std::vector<int>& optional) {
// process vector
}
Are there reasons to prefer one solution over the other?
I slightly prefer the second one because I can make the vector a const reference, since it is, when provided, only read, not written. Also, the interface looks cleaner (isn't NULL just a hack?). And the performance difference resulting from the indirect function call is probably optimized away.
Yet, I often see the first solution in code. Are there compelling reasons to prefer it, apart from programmer laziness?
I would not use either approach.
In this context, the purpose of foo() seems to be to process a vector. That is, foo()'s job is to process the vector.
But in the second version of foo(), it is implicitly given a second job: to create the vector. The semantics between foo() version 1 and foo() version 2 are not the same.
Instead of doing this, I would consider having just one foo() function to process a vector, and another function which creates the vector, if you need such a thing.
For example:
void foo(int i, const std::vector<int>& optional) {
// process vector
}
std::vector<int>* makeVector() {
return new std::vector<int>;
}
Obviously these functions are trivial, and if all makeVector() needs to do to get it's job done is literally just call new, then there may be no point in having the makeVector() function. But I'm sure that in your actual situation these functions do much more than what is being shown here, and my code above illustrates a fundamental approach to semantic design: give one function one job to do.
The design I have above for the foo() function also illustrates another fundamental approach that I personally use in my code when it comes to designing interfaces -- which includes function signatures, classes, etc. That is this: I believe that a good interface is 1) easy and intuitive to use correctly, and 2) difficult or impossible to use incorrectly . In the case of the foo() function we are implictly saying that, with my design, the vector is required to already exist and be 'ready'. By designing foo() to take a reference instead of a pointer, it is both intuitive that the caller must already have a vector, and they are going to have a hard time passing in something that isn't a ready-to-go vector.
I would definitely favour the 2nd approach of overloaded methods.
The first approach (optional parameters) blurs the definition of the method as it no longer has a single well-defined purpose. This in turn increases the complexity of the code, making it more difficult for someone not familiar with it to understand it.
With the second approach (overloaded methods), each method has a clear purpose. Each method is well-structured and cohesive. Some additional notes:
If there's code which needs to be duplicated into both methods, this can be extracted out into a separate method and each overloaded method could call this external method.
I would go a step further and name each method differently to indicate the differences between the methods. This will make the code more self-documenting.
While I do understand the complaints of many people regarding default parameters and overloads, there seems to be a lack of understanding to the benefits that these features provide.
Default Parameter Values:
First I want to point out that upon initial design of a project, there should be little to no use for defaults if well designed. However, where defaults' greatest assets comes into play is with existing projects and well established APIs. I work on projects that consist of millions of existing lines of code and do not have the luxury to re-code them all. So when you wish to add a new feature which requires an extra parameter; a default is needed for the new parameter. Otherwise you will break everyone that uses your project. Which would be fine with me personally, but I doubt your company or users of your product/API would appreciate having to re-code their projects on every update. Simply, Defaults are great for backwards compatibility! This is usually the reason you will see defaults in big APIs or existing projects.
Function Overrides:
The benefit of function overrides is that they allow for the sharing of a functionality concept, but with with different options/parameters. However, many times I see function overrides lazily used to provide starkly different functionality, with just slightly different parameters. In this case they should each have separately named functions, pertaining to their specific functionality (As with the OP's example).
These, features of c/c++ are good and work well when used properly. Which can be said of most any programming feature. It is when they are abused/misused that they cause problems.
Disclaimer:
I know that this question is a few years old, but since these answers came up in my search results today (2012), I felt this needed further addressing for future readers.
I agree, I would use two functions. Basically, you have two different use cases, so it makes sense to have two different implementations.
I find that the more C++ code I write, the fewer parameter defaults I have - I wouldn't really shed any tears if the feature was deprecated, though I would have to re-write a shed load of old code!
A references can't be NULL in C++, a really good solution would be to use Nullable template.
This would let you do things is ref.isNull()
Here you can use this:
template<class T>
class Nullable {
public:
Nullable() {
m_set = false;
}
explicit
Nullable(T value) {
m_value = value;
m_set = true;
}
Nullable(const Nullable &src) {
m_set = src.m_set;
if(m_set)
m_value = src.m_value;
}
Nullable & operator =(const Nullable &RHS) {
m_set = RHS.m_set;
if(m_set)
m_value = RHS.m_value;
return *this;
}
bool operator ==(const Nullable &RHS) const {
if(!m_set && !RHS.m_set)
return true;
if(m_set != RHS.m_set)
return false;
return m_value == RHS.m_value;
}
bool operator !=(const Nullable &RHS) const {
return !operator==(RHS);
}
bool GetSet() const {
return m_set;
}
const T &GetValue() const {
return m_value;
}
T GetValueDefault(const T &defaultValue) const {
if(m_set)
return m_value;
return defaultValue;
}
void SetValue(const T &value) {
m_value = value;
m_set = true;
}
void Clear()
{
m_set = false;
}
private:
T m_value;
bool m_set;
};
Now you can have
void foo(int i, Nullable<AnyClass> &optional = Nullable<AnyClass>()) {
//you can do
if(optional.isNull()) {
}
}
I usually avoid the first case. Note that those two functions are different in what they do. One of them fills a vector with some data. The other doesn't (just accept the data from the caller). I tend to name differently functions that actually do different things. In fact, even as you write them, they are two functions:
foo_default (or just foo)
foo_with_values
At least I find this distinction cleaner in the long therm, and for the occasional library/functions user.
I, too, prefer the second one. While there are not much difference between the two, you are basically using the functionality of the primary method in the foo(int i) overload and the primary overload would work perfectly without caring about existence of lack of the other one, so there is more separation of concerns in the overload version.
In C++ you should avoid allowing valid NULL parameters whenever possible. The reason is that it substantially reduces callsite documentation. I know this sounds extreme but I work with APIs that take upwards of 10-20 parameters, half of which can validly be NULL. The resulting code is almost unreadable
SomeFunction(NULL, pName, NULL, pDestination);
If you were to switch it to force const references the code is simply forced to be more readable.
SomeFunction(
Location::Hidden(),
pName,
SomeOtherValue::Empty(),
pDestination);
I'm squarely in the "overload" camp. Others have added specifics about your actual code example but I wanted to add what I feel are the benefits of using overloads versus defaults for the general case.
Any parameter can be "defaulted"
No gotcha if an overriding function uses a different value for its default.
It's not necessary to add "hacky" constructors to existing types in order to allow them to have default.
Output parameters can be defaulted without needing to use pointers or hacky global objects.
To put some code examples on each:
Any parameter can be defaulted:
class A {}; class B {}; class C {};
void foo (A const &, B const &, C const &);
inline void foo (A const & a, C const & c)
{
foo (a, B (), c); // 'B' defaulted
}
No danger of overriding functions having different values for the default:
class A {
public:
virtual void foo (int i = 0);
};
class B : public A {
public:
virtual void foo (int i = 100);
};
void bar (A & a)
{
a.foo (); // Always uses '0', no matter of dynamic type of 'a'
}
It's not necessary to add "hacky" constructors to existing types in order to allow them to be defaulted:
struct POD {
int i;
int j;
};
void foo (POD p); // Adding default (other than {0, 0})
// would require constructor to be added
inline void foo ()
{
POD p = { 1, 2 };
foo (p);
}
Output parameters can be defaulted without needing to use pointers or hacky global objects:
void foo (int i, int & j); // Default requires global "dummy"
// or 'j' should be pointer.
inline void foo (int i)
{
int j;
foo (i, j);
}
The only exception to the rule re overloading versus defaults is for constructors where it's currently not possible for a constructor to forward to another. (I believe C++ 0x will solve that though).
I would favour a third option:
Separate into two functions, but do not overload.
Overloads, by nature, are less usable. They require the user to become aware of two options and figure out what the difference between them is, and if they're so inclined, to also check the documentation or the code to ensure which is which.
I would have one function that takes the parameter,
and one that is called "createVectorAndFoo" or something like that (obviously naming becomes easier with real problems).
While this violates the "two responsibilities for function" rule (and gives it a long name), I believe this is preferable when your function really does do two things (create vector and foo it).
Generally I agree with others' suggestion to use a two-function approach. However, if the vector created when the 1-parameter form is used is always the same, you could simplify things by instead making it static and using a default const& parameter instead:
// Either at global scope, or (better) inside a class
static vector<int> default_vector = populate_default_vector();
void foo(int i, std::vector<int> const& optional = default_vector) {
...
}
The first way is poorer because you cannot tell if you accidentally passed in NULL or if it was done on purpose... if it was an accident then you have likely caused a bug.
With the second one you can test (assert, whatever) for NULL and handle it appropriately.