Sets consisting of a combination of elements and other sets being used to construct sets in C++
I have several standard sets of integers that I need to be able to access from multiple translation units. The goal is to take these standard sets and put them into local sets depending on the context of the code.
For example, the best solution I have is:
#include <boost/assign/list_of.hpp>
#include <set>
const std::set<int> set9 =
boost::assign::list_of(4)(10)(108);
const std::set<int> set10 =
boost::assign::list_of(3)(5)(10)(108);
const std::se开发者_开发知识库t<int> set11 =
boost::assign::list_of(2)(3)(5)(101);
int main(void)
{
std::set<int> my_set(set9);
my_set.insert(set11.begin(), set11.end());
return 0;
}
They don't need to be constant globals, in fact, I would probably prefer functions, but if they are functions then I would have to add an extra line and extra set variable every time I want to use more than one.
It would look something like this (with one more standard set than before):
std::set<int> my_set(get_set9());
std::set<int> extra_line(get_set11());
my_set.insert(extra_line.begin(), extra_line.end());
std::set<int> another_extra_line(get_set12());
my_set.insert(another_extra_line.begin(), another_extra_line.end());
Unless I am missing something?
The reason I would prefer functions is that there is additional complexity. Among the constant sets there are repeated values with connected meanings so that I don't want to repeat them each time in case there is a change (and to prevent code duplication).
In my previous example say that 10 and 108 are connected and should always appear together. If these were functions I could just have get_set11() and get_set12() call a common function (like get_set2() which just has 10 and 108). However, with the constant set approach I'm not sure how to build these constant sets containing other sets. The best I've come up with is:
#include <boost/assign/list_of.hpp>
#include <set>
#define APPLY_COMMON_SET(prev) \
prev(10)(8)
const std::set<int> set2 =
APPLY_COMMON_SET(boost::assign::list_of);
const std::set<int> set9 =
APPLY_COMMON_SET(boost::assign::list_of(4));
const std::set<int> set10 =
APPLY_COMMON_SET(boost::assign::list_of(3)(5));
const std::set<int> set11 =
boost::assign::list_of(2)(3)(5)(101);
#undef APPLY_COMMON_SET
int main(void)
{
std::set<int> my_set(set9);
my_set.insert(set11.begin(), set11.end());
return 0;
}
Which works, but I'd prefer to avoid the pre-processor macro.
This doesn't compile, but I would like to be able to do something like this:
const std::set<int> set2 =
boost::assign::list_of(10)(108)
const std::set<int> set9 =
boost::assign::list_of(4) + set2;
const std::set<int> set10 =
boost::assign::list_of(3)(5) + set2;
Is there a way to do this without macros, or is that my only choice?
Any particular performance constraints? You could just implement the addition you use at the end:
typedef std::set<int> intset;
intset onion(intset lhscp, const intset &rhs) {
lhscp.insert(rhs.begin(), rhs.end());
return lhscp;
}
const intset set10 = onion(boost::assign::list_of(2)(5), set2);
A local macro (as you have here, the key is the #undef) is probably the cleanest solution as you present the problem. However, you've not said much about why you're doing this, and that information may provide a better solution.
I would use the macro in the "opposite" direction:
#define COMMON (10)(8)
const std::set<int> set10 =
boost::assign::list_of(3)(5) COMMON;
#undef COMMON
To steal and slightly tweak Steve's answer (since I can't edit it). I think the best solution is to implement operator+ for sets.
std::set<int> operator+(std::set<int> lhs, const std::set<int> &rhs)
{
lhs.insert(rhs.begin(), rhs.end());
return lhs;
}
After this is done it doesn't matter whether the sets come from global constants or functions, they can all go as arguments to the constructors:
#include <boost/assign/list_of.hpp>
#include <stdio.h>
#include <set>
typedef std::set<int> intset;
intset operator+(intset lhs, const intset &rhs)
{
lhs.insert(rhs.begin(), rhs.end());
return lhs;
}
const intset set2 =
boost::assign::list_of(10)(108);
const intset set9 =
boost::assign::list_of(4) + set2;
intset get_set11(bool flag)
{
if(flag)
return set2 + boost::assign::list_of(6);
else
return set9;
}
int main(void)
{
intset my_set(set9 + get_set11(true));
return 0;
}
精彩评论