I am designing a class which (among other things) acts as a vertex in an undirected graph.
#include <iterator>
#include <string>
class Node
{
public:
explicit Node(const std::string& name);
Node(const Node&);
Node(Node&&);
class iterator
: public std::iterator<std::random_access_iterator_tag, const Node>
{
//...
};
class container_proxy
{
public:
iterator begin() const;
iterator end() const;
private:
//...
};
container_proxy neighbors() const;
add_link(Node& other);
//...
private:
//...
};
// to support: for (const Node& neighbor : node.neighbors())
Node::iterator begin(const Node::container_proxy&);
Node::iterator end(const Node::container_proxy&);
Now I want to define a function link_complete
which:
- takes any number of arguments
- allows non-
const
Node
lvalues (parameter typeNode&
) - allows non-
const
Node
rvalues (parameter typeNode&&
) - does not allow any other parameter type.
An example usage:
Node ret_by_value();
void example_test(Node& x, Node&& y)
{
link_complete(x, ret_by_value(), std::move(y), Node("test"));
}
Here's the solution I came up with:
#include <initializer_list>
#include <type_traits>
class Node {
//...
public:
static void link_complete(std::initializer_list<Node*> node_list);
};
template <typename ... Types>
struct template_all; // UNDEFINED
template <>
struct template_all<>
: public std::true_type {};
template <typename ... Types>
struct template_all<std::false_type, Types...>
: public std::false_type {};
template <typename ... Types>
struct template_all<std::true_type, Types...>
: public template_all<Types...>::type {};
template <typename ... Args>
auto link_complete(Args&& ... args) ->
typename std::enable_if<
template_all<
typename std::is_same<
typename std::remove_reference<Args>::type,
Node
>::type ...
>::value,
void
>::type
{
Node::link_complete( { &args... } );
}
It seems to work as required, but I'm wondering if there was a simpler or "prettier" way to do it, or maybe a way to improve that template_all
helper type. All C++11, TR1, and Boost features are welcome. I did notice boost::mpl::and_
looks similar to my template_all
helper type, but Boost MPL seems like a tricky learning curve and/or overkill for this problem.