I’m currently attending ACCU2013 at Bristol and saw Jonathan Wakely’s presentation on SFINAE (Substitution Failure Is Not An Error) this morning.
This is a traditional SFINAE example using type traits. true_type and false_type just need to have different sizes, then we can use function template specialization to differentiate between two cases.
typedef char true_type; typedef double false_type; template<class T> true_type is_iter( typename T::iterator_category* t ); template<class T> false_type is_iter(...); template<class T> struct is_iterator { static const bool value = (sizeof(is_iter<T>(0)) == sizeof(true_type)); }; void testTypeTrait() { std::cout << "Try int " << is_iterator<int>::value << "\n"; << "Try vector<int>::iterator " << is_iterator<std::vector<int>::iterator>::value << "\n"; }
This example later in the presentation really stood out – a step towards Concepts, it shows syntax available today for restricting the types that will compile with a given template (thanks to C++11 aliasing and default arguments for template parameters):
class WidgetBase {}; class Widget : public WidgetBase {}; class Bodget {}; class Decorator { private: template<class T> using IsDerivedWidget = typename std::enable_if< std::is_base_of<WidgetBase, T>::value>::type; public: template<class T, class Requires = IsDerivedWidget<T>> Decorator( const T& ) {} };
So if I instantiate Decorator with Widget, it compiles (because Widget derives from WidgetBase), but instantiating with Bodget yields a compiler error (because Bodget does not inherit from WidgetBase).
Widget w; Decorator decoratedWidget( w ); Bodget b; Decorator decoratedBodget( b ); // Error
This code all compiles with recent versions of gcc (e.g. 4.7). Under Visual Studio, only the traditional example compiles (default arguments for function templates are not yet supported, neither is aliasing, not even with the Nov ’12 CTP).
Pingback: ACCU: Introducing Concepts for C++ | musingstudio