Sometimes, we need a metafunction to have this effect which is that when we pass a type with certain series of tag, if the type contain the tag, then return the tag, otherwise just return the void.
This might be a simple metafunction, but when I encounter this trick at the very first time, it confused me a lot. The code snippit as follows:
#include <bits/stdc++.h>
#include <boost/graph/properties.hpp>
#include <boost/graph/adjacency_list.hpp>
using namespace boost;
template <typename A> struct return_void {typedef void type;};
template <typename Graph, typename Enable = void>
struct graph_tag_or_void {
typedef void type;
};
template <typename Graph>
struct graph_tag_or_void<Graph, typename return_void<typename Graph::graph_tag>::type> {
typedef typename Graph::graph_tag type;
};
typedef adjacency_list<vecS, vecS, directedS> Graph;
void tst() {
std::cout << std::is_same<return_void<Graph::graph_tag>::type, void>::value << std::endl;
std::cout << std::is_same<Graph::graph_tag, graph_tag_or_void<Graph>::type>::value << std::endl;
}
int main() {
tst();
return 0;
}
As you can see, if a type have graph_tag
, then graph_tag_or_void<Graph>::type
will return Graph::graph_type
and void
on the contrary. Here I will explain why that happened.
Firstly we have a metafunctionreturn_void
which always return void
from::type
. This function may seemed useless, but in the metafunction graph_tag_or_void
, this function can help us to detect whether the type have graph_tag
.
If it does have graph_tag
, then the second specialization will be called. On the other hand, it will just call the first one, which always return void
.