#include #include using namespace std; using namespace boost; struct True { static const bool value = true; }; struct False { static const bool value = false; }; // Here are some graph structures. Some of them define the type "OneTag" // to True or False, some does not. Not defining a tag is (or at least // should be) equivalent to defining it to "False". struct Graph1 {}; struct Graph2 { typedef True OneTag; }; struct Graph3 { typedef False OneTag; }; /**************** The first method to use tags ****************/ template struct HasOneTag { typedef False TheTag; }; // specialization for those graphs which defined the tag to be true: template struct HasOneTag::type > { typedef True TheTag; }; template int cn1(const Graph &, False) { return 0; } template int cn1(const Graph &, True) { return 1; } template int cn1(const Graph &g) { return cn1(g, typename HasOneTag::TheTag()); } /**************** The second method ****************/ // An artificial type to provoke a conversion to avoid ambuguity... template struct Wrap { const T &value; Wrap(const T &t) : value(t) {} }; template typename enable_if::type _cn2(const Graph &) { return 1; } template int _cn2(Wrap) { return 0; } template int cn2(const Graph& g) { return _cn2(g); } int main() { Graph1 g1; Graph2 g2; Graph3 g3; cout << "The first method:\n"; cout << "G1: " << cn1(g1) << endl; cout << "G2: " << cn1(g2) << endl; cout << "G3: " << cn1(g3) << endl; cout << "The second method:\n"; cout << "G1: " << cn2(g1) << endl; cout << "G2: " << cn2(g2) << endl; cout << "G3: " << cn2(g3) << endl; }