1

I would like to have a template on container and two tuple types, so that I can merge two following functions into one:

template<typename Container>
void vblock(int row, int col, const Container& container) {
  foreach( const typename Container::value_type& item, container ) {
    cell(row, col, item);
    ++row;
  }
}

template<typename container, typename T1, typename T2>
void vblock(int row, int col,
          const std::list<typename boost::tuple<T1, T2> >& container) {
  typedef boost::tuple<T1, T2> Tuple;
  foreach( const Tuple& item, container ) {
    cell(row, col, item.template get<0>());
    cell(row + 1, col, item.template get<1>());
    ++col;
  }
}

template<typename container, typename T1, typename T2>
void vblock(int row, int col,
          const std::set<typename boost::tuple<T1, T2> >& container) {
  typedef boost::tuple<T1, T2> Tuple;
  foreach( const Tuple& item, container ) {
    cell(row, col, item.template get<0>());
    cell(row + 1, col, item.template get<1>());
    ++col;
  }
}

I have already checked C++ Templates - Specifying a container type and that containers element type that it holds and C++ Template class using STL container and a typedef, but they don't answer my question.

The question simple C++ templates suited for STL Containers is most similar to mine, but I couldn't figure out how to add templates for boost::tuple. Thanks!

Community
  • 1
  • 1
marko.ristin
  • 643
  • 8
  • 6
  • 1
    How about just `template void vblock(int row, int col, C const & container)`? What's the actual implementation? – Kerrek SB Aug 15 '12 at 13:32
  • @Kerrek SB: but then I couldn't access the tuple types, could I? – marko.ristin Aug 15 '12 at 13:35
  • @marko: Basically, you assume that they're tuples (or more accurately, you assume that they can be used with boost::get). If the container supports that interface, then it will work (so it will work for tuples), and if it doesn't, it will fail to compile. – Dave S Aug 15 '12 at 13:36
  • @marko.ristin: Sure: `typedef typename C::value_type tuple_type;` etc. – Kerrek SB Aug 15 '12 at 13:37
  • @Kerrek SB: sorry, I forgot to include the full implementation. Is the enable_if logic the only way to achieve what I want? – marko.ristin Aug 15 '12 at 13:42
  • 1
    @marko.ristin: No, you only need `enable_if` to avoid having impossible overloads in the overload set, but that's unlikely to be an issue. – Kerrek SB Aug 15 '12 at 13:48

2 Answers2

1

Keep it simple:

template <typename C>
void vblock(int row, int col, C const & container)
{
    typedef typename C::value_type tuple_type;
    typedef typename boost::element<0, tuple_type>::type first_type;
    typedef typename boost::element<1, tuple_type>::type second_type;

    // ...
}

You could add some enable_if logic to the function declaration to prevent the creation of impossible overloads, but perhaps that's not needed just yet.

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
0

The solution by Kerrek SB is good and applicable for a general case (I voted for it).

In the end, I settled with a slightly different implementation that uses function overloading which is a possible alternative especially because it doesn't require enable_if's and is still kind of elegant:

template<typename Container>
void vblock(int row, int col, const Container& container) {
  foreach( const typename Container::value_type& item, container ) {
    vblock_cell_impl(row, col, item);
    ++row;
  }
}

template<typename T>
void vblock_cell_impl(int row, int col, const T& item) {
  cell(row, col, item);
}

template<typename T1, typename T2>
void hblock_cell_impl(int row, int col, const boost::tuple<T1, T2>& item) {
  cell(row, col, item.template get<0>());
  cell(row + 1, col, item.template get<1>());
}
marko.ristin
  • 643
  • 8
  • 6