template <typename T> // unless it s an unqualified pointer struct IsPtr<T *> { enum { r = true }; };

Similar documents
Introduction to Standard C++

Appendix. Grammar. A.1 Introduction. A.2 Keywords. There is no worse danger for a teacher than to teach words instead of things.

Tokens, Expressions and Control Structures

Using Enum Structs as Bitfields

CS93SI Handout 04 Spring 2006 Apr Review Answers

} else if( Ellipse *e = dynamic_cast<ellipse *>(shape) ) { } else if( Square *s = dynamic_cast<square *>(shape) ) {

Instantiation of Template class

On the correctness of template metaprograms

Short Notes of CS201

Overload Resolution. Ansel Sermersheim & Barbara Geller ACCU / C++ June 2018

Basic Types, Variables, Literals, Constants

CS201 - Introduction to Programming Glossary By

Overload Resolution. Ansel Sermersheim & Barbara Geller Amsterdam C++ Group March 2019

Decltype (revision 6): proposed wording

Simulating Partial Specialization

P.G.TRB - COMPUTER SCIENCE. c) data processing language d) none of the above

1d: tests knowing about bitwise fields and union/struct differences.

An Introduction to Template Metaprogramming

DETAILED SYLLABUS INTRODUCTION TO C LANGUAGE

Programming in C++ 4. The lexical basis of C++

OBJECT ORIENTED PROGRAMMING USING C++

Part X. Advanced C ++

Review of the C Programming Language for Principles of Operating Systems

Introduction to Core C++

Object-Oriented Programming for Scientific Computing

C++ Template Meta. A basic introduction to basic C++ techniques used in template metaprogramming.

Explicit Conversion Operator Draft Working Paper

Haskell and C++ Template Metaprogramming. Bartosz Milewski

Agenda. The main body and cout. Fundamental data types. Declarations and definitions. Control structures

Design Patterns in C++

Review of the C Programming Language

CS349/SE382 A1 C Programming Tutorial

boost::enable_if Deep Down Boostimagical Fun Christian Bay and Kasper A Andersen Department of Computer Science University of Copenhagen

Design Patterns in C++

Debug C++ Without Running. Anastasia Kazakova

Function Binding. Special thanks to: John Edwards. Randy Gaul

See also Index of Code Examples, page 245

P1267R0: Custom Constraint Diagnostics

Object Oriented Programming in C#

Basic Templates Intro

Introduction to C++ Systems Programming

Variables Data types Variable I/O. C introduction. Variables. Variables 1 / 14

The Foundation of C++: The C Subset An Overview of C p. 3 The Origins and History of C p. 4 C Is a Middle-Level Language p. 5 C Is a Structured

Binghamton University. CS-211 Fall Syntax. What the Compiler needs to understand your program

Chapter 15 - C++ As A "Better C"

A Fast Review of C Essentials Part I

Lecture 2 Polymorphism, Traits, Policies, and Inheritance

Pointers, Dynamic Data, and Reference Types

Variables. Data Types.

C++ Coding Standards. 101 Rules, Guidelines, and Best Practices. Herb Sutter Andrei Alexandrescu. Boston. 'Y.'YAddison-Wesley

Proposal for Extending the switch statement

C++ C and C++ C++ fundamental types. C++ enumeration. To quote Bjarne Stroustrup: 5. Overloading Namespaces Classes

C Programming. Course Outline. C Programming. Code: MBD101. Duration: 10 Hours. Prerequisites:

G205 Fundamentals of Computer Engineering. CLASS 3, Wed. Sept Stefano Basagni Fall 2004 M-W, 1:30pm-3:10pm

Introduction to Programming

Modern C++ Interfaces

Antitrust Notice. Using C++: A First Step. Overview 3/17/2011

ME240 Computation for Mechanical Engineering. Lecture 4. C++ Data Types

COMP 2355 Introduction to Systems Programming

A Taxonomy of Expression Value Categories

Item 4: Extensible Templates: Via Inheritance or Traits?

Lambdas in unevaluated contexts

Introduction to C++ Professor Hugh C. Lauer CS-2303, System Programming Concepts

Recap. ANSI C Reserved Words C++ Multimedia Programming Lecture 2. Erwin M. Bakker Joachim Rijsdam

Fast Introduction to Object Oriented Programming and C++

Advanced Systems Programming

14. Pointers, Algorithms, Iterators and Containers II

Chapter 16. Templates. Copyright 2010 Pearson Addison-Wesley. All rights reserved

Operator Overloading and Templates. Linear Search. Linear Search in C++ second attempt. Linear Search in C++ first attempt

Part III. Advanced C ++

University of Technology. Laser & Optoelectronics Engineering Department. C++ Lab.

Programming in C and C++

Advanced C++ Programming Workshop (With C++11, C++14, C++17) & Design Patterns

Programming. C++ Basics

COMP 181. Agenda. Midterm topics. Today: type checking. Purpose of types. Type errors. Type checking

Definitions of scalar type and fundamental type

Semantics of C++ Hauptseminar im Wintersemester 2009/10 Templates

Introduction to C++ Introduction. Structure of a C++ Program. Structure of a C++ Program. C++ widely-used general-purpose programming language

C++ (Non for C Programmer) (BT307) 40 Hours

Writing an ANSI C Program Getting Ready to Program A First Program Variables, Expressions, and Assignments Initialization The Use of #define and

Introduction to Programming Using Java (98-388)

Introduction to C++ with content from

Object-Oriented Programming for Scientific Computing

@odinthenerd. not the god. Auto-Intern GmbH 1

Static If I Had a Hammer

C++14 Reflections Without Macros, Markup nor External Tooling

VARIABLES AND CONSTANTS

An Oddysey in C++ A Guided Tour of Modern C++ Per Karlström Upplysningen

Intermediate Programming, Spring 2017*

Generalized Constant Expressions

Variables in C. Variables in C. What Are Variables in C? CMSC 104, Fall 2012 John Y. Park

EL6483: Brief Overview of C Programming Language

Advanced C++ Topics. Alexander Warg, 2017

The following is an excerpt from Scott Meyers new book, Effective C++, Third Edition: 55 Specific Ways to Improve Your Programs and Designs.

Templates (again) Professor Hugh C. Lauer CS-2303, System Programming Concepts

DECLARAING AND INITIALIZING POINTERS

6.096 Introduction to C++ January (IAP) 2009

ET156 Introduction to C Programming


DECLARATIONS. Character Set, Keywords, Identifiers, Constants, Variables. Designed by Parul Khurana, LIECA.

Transcription:

SFINAE Sono Buoni SFINAE In attempting to use function template argument deduction to select among a number of candidate function templates, a C++ compiler may attempt an instantiation that fails on one or more of them. void f( T ); void f( T * ); f( 1024 ); // instantiates first f Even though substitution of the integer for T * in the second f function template would have been incorrect, the attempted substitution does not give rise to an error provided that a correct substitution is found. In this case, the first f is instantiated, and there is no error. Thus, we have the substitution failure is not an error concept, dubbed SFINAE by Vandevoorde and Josuttis. 1 SFINAE is an important property in that, without it, it would be difficult to overload function templates; the combination of argument deduction and overloading would render many uses of a set of overloaded function templates illegal. But SFINAE is also valuable as a metaprogramming technique. SFINAE vs. Partial Specialization Consider a simple utility that can be used to determine whether a type is a pointer type: // T is not a pointer struct IsPtr { enum { r = false // unless it s an unqualified pointer struct IsPtr<T *> { enum { r = true // or a const pointer struct IsPtr<T * const> { enum { r = true // or a volatile pointer struct IsPtr<T * volatile> { enum { r = true // or a const volatile pointer 1 Vandevoorde and Josuttis, C++ Templates, Addison-Wesley 2003. - 1 -

struct IsPtr<T * const volatile> { enum { r = true This can be used to make a compile time, metaprogrammed decision. For example, we can choose alternate container implementations based on whether the container s element type is a pointer or not. class SList { typedef typename Select< IsPtr<T>::r, Cptr< DePtr<T> >, T >::R ElemType; private: struct Node { Node *next_; ElemType el_; } *head_; We can use SFINAE to achieve a similar result. typedef True char; // sizeof(true) == 1 typedef struct { char a[2]; } False; // sizeof(false) > 1 True isptr( T * ); False isptr( ); #define is_ptr( e ) (sizeof(isptr(e))==sizeof(true)) Here, we can determine whether the type of an expression is a pointer through a combination of function template argument deduction and SFINAE. If the expression e has pointer type, the compiler will match the template function isptr, otherwise it will match the non-template isptr function with the ellipsis formal argument. SFINAE assures us that the attempt to match the template isptr with a non-pointer will not result in a compile time error. The second bit of magic is the use of sizeof in the is_ptr macro. Notice that neither isptr function is defined. This is correct, because they are never actually called. The appearance of the function call in a sizeof expression causes the compiler to perform argument deduction and function matching, but does not cause a function call to be generated. sizeof is interested only in the size of the return type of the function that would have been called. We can then check the size of the function s return type to determine which function was matched. If the compiler selected the function template, then the expression e had pointer type. Note that we did not have to special case for const pointers, volatile pointers, and const volatile pointers as we did for the analogous IsPtr facility above that we implemented with class template partial specialization. As part of function template argument - 2 -

deduction, the compiler will ignore first level cv-qualifiers (const and volatile) as well as reference modifiers. (If we d wanted to distinguish differently qualified pointer types, then we d have declared four different template isptr functions to take formal argument types of reference to pointer.) Note also that we do not have to be concerned about incorrectly identifying as a pointer type a user-defined type that has a conversion operator. The compiler employs a very restricted list of conversions on the actual arguments during function template argument deduction, and user-defined conversions are not on the list. class NotAPtr { operator T *() const; // conversion operator NotAPtr<int> nap; Select< is_ptr(nap), X, Y>::R temp; //temp is of type Y SFINAE Examples Is this type a class type? struct IsClass { template <class C> static True isclass( int C::* ); template <typename C> static False isclass( ); enum { r = sizeof(isclass<t>::isclass<t>(0)) == sizeof(true) Is This Type a Pointer to a Class Type? struct IsPtrToClass { enum { r = IsPtr<T>::r && IsClass<typename DePtr<T>::R>::r Does This Class Contain The Typename iterator? This is abstracted from Vandevoorde and Josuttis. Of course, this can be implemented to ask the question of any nested typename, not just iterator. template <class C> True hasiterator( typename C::iterator const * ); False hasiterator( ); #define has_iterator( C ) (sizeof(hasiterator<c>(0))==sizeof(true)) Is This a Non-Static Member Function? This is implemented to answer the question for member functions of 0, 1, or two arguments, but can easily be extended to any fixed number. template <typename R, class C> - 3 -

True ismemf( R (C::*)( ) ); template <typename R, typename A, class C> True ismemf( R (C::*)(A) ); template <typename R, typename A1, typename A2, class C> True ismemf( R (C::*)(A1,A2) ); False ismemf( ); #define is_member_func( f ) (sizeof( ismemf(f) ) == sizeof(true)) Can I Convert a T1 to a T2? This is from Andrei Alexandrescu. Note that this mechanism will detect both predefined and user-defined conversions. template <typename T1, typename T2> struct CanConvert { static True canconvert( T2 ); static False canconvert(... ); static T1 maket1( ); enum { r = sizeof(canconvert( maket1( ) )) == sizeof(true) Appendix: Miscellaneous Utilities Here s the source code for some utilities that appeared above. Select This implementation of Select is a modified form of the Select that appears in Andrei Alexandrescu s Loki Library. It is basically a compile time if-statement whose result type is either the second or third argument, based on the first argument. template <bool, typename A, typename B> struct Select { typedef A R; Cptr template <typename A, typename B> struct Select<false,A,B> { typedef B R; Cptr is a modified form of Nicolai Josuttis s CountedPointer that appeared in his The C++ Standard Library. Cptr is a smart pointer that reference counts and garbage collects the object to which it refers. - 4 -

template <class T> class Cptr { public: Cptr( T *p ) : p_( p ), c_( new long( 1 ) ) { } ~Cptr() { if(!--*c_ ) { delete c_; delete p_; } } Cptr( const Cptr &init ) : p_( init.p_ ), c_( init.c_ ) { ++*c_; } Cptr &operator =( const Cptr &rhs ) { if( this!= &rhs ) { if(!--*c_ ) { delete c_; delete p_; } p_ = rhs.p_; ++*(c_ = rhs.c_); // macho! } return *this; } T &operator *() const { return *p_; } T *operator ->() const { return p_; } private: T *p_; long *c_; DePtr DePtr strips away a single pointer modifier from the type used to instantiate it, if possible. struct DePtr { typedef T R; // T is not a ptr; result is same struct DePtr<T *> { struct DePtr<T * const> { struct DePtr<T * volatile> { struct DePtr<T * const volatile> { - 5 -

Copyright 2002 by Stephen C. Dewhurst - 6 -