Is there is any difference between using a std::tuple
and a data-only struct
?
typedef std::tuple foo_t;
s
There shouldn't be a performance difference (even an insignificant one). At least in the normal case, they will result in the same memory layout. Nonetheless, casting between them probably isn't required to work (though I'd guess there's a pretty fair chance it normally will).
Don't worry about speed or layout, that's nano-optimisation, and depends on the compiler, and there's never enough difference to influence your decision.
You use a struct for things that meaningfully belong together to form a whole.
You use a tuple for things that are together coincidentally. You can use a tuple spontaneously in your code.
If you're using several different tuples in your code you can get away with condensing the number of functors you are using. I say this because I've often used the following forms of functors:
template<int N>
struct tuple_less{
template<typename Tuple>
bool operator()(const Tuple& aLeft, const Tuple& aRight) const{
typedef typename boost::tuples::element<N, Tuple>::type value_type;
BOOST_CONCEPT_REQUIRES((boost::LessThanComparable<value_type>));
return boost::tuples::get<N>(aLeft) < boost::tuples::get<N>(aRight);
}
};
This might seem like overkill but for each place within the struct I'd have to make a whole new functor object using a struct but for a tuple, I just change N
. Better than that, I can do this for every single tuple as opposed to creating a whole new functor for each struct and for each member variable. If I have N structs with M member variables that NxM functors I would need to create (worse case scenario) that can be condensed down to one little bit of code.
Naturally, if you're going to go with the Tuple way, you're also going to need to create Enums for working with them:
typedef boost::tuples::tuple<double,double,double> JackPot;
enum JackPotIndex{
MAX_POT,
CURRENT_POT,
MIN_POT
};
and boom, you're code is completely readable:
double guessWhatThisIs = boost::tuples::get<CURRENT_POT>(someJackPotTuple);
because it describes itself when you want to get the items contained within it.
Well, a POD struct can often be (ab)used in low-level contiguous chunk reading and serializing. A tuple might be more optimized in certain situations and support more functions, as you said.
Use whatever is more appropriate for the situation, there ain't no general preference. I think (but I haven't benchmarked it) that performance differences won't be significant. The data layout is most likely not compatible and implementation specific.
As far as the "generic function" go, Boost.Fusion deserves some love... and especially BOOST_FUSION_ADAPT_STRUCT.
Ripping from the page: ABRACADBRA
namespace demo
{
struct employee
{
std::string name;
int age;
};
}
// demo::employee is now a Fusion sequence
BOOST_FUSION_ADAPT_STRUCT(
demo::employee
(std::string, name)
(int, age))
This means that all Fusion algorithms are now applicable to the struct demo::employee
.
EDIT: Regarding the performance difference or layout compatibility, tuple
's layout is implementation defined so not compatible (and thus you should not cast between either representation) and in general I would expect no difference performance-wise (at least in Release) thanks to the inlining of get<N>
.
I know it is an old theme, however I am now about to make a decision about part of my project: should I go the tuple-way or struct-way. After reading this thread I have some ideas.
About the wheaties and the performance test: please note that you can usually use memcpy, memset and similar tricks for structs. This would make the performance MUCH better than for tuples.
I see some advantages in tuples:
I have searched the web and eventually reached this page: https://arne-mertz.de/2017/03/smelly-pair-tuple/
Generally I agree with a final conclusion from above.