Home > C++ (C Plus Plus), LinkedIn, Programmazione > Esempio di type traits (C++0x)…

Esempio di type traits (C++0x)…

Una delle feature che più apprezzo del C++ è il supporto alla template metaprogramming e a tutto ciò che le ruota attorno.

Il prossimo standard C++, C++0x, introduce alcune interessanti novità che possono tornare molto utili in questo ambito come ad esempio i type trait.

Type traits?

Un type trait non è altro che una caratteristica particolare di un tipo. Ad esempio un intero è un tipo primitivo, scalare, non è un oggetto, … Ciascuna di queste caratteristiche è un trait, un “tratto” di un tipo.

Conoscere i “tratti” di un determinato tipo permette di effettuare interessanti operazioni: pensate ad una funzione-template che sulla base del tipo specifico passato in input e dei suoi tratti seleziona l’algoritmo migliore da usare in quel contesto.

In un certo senso l’introduzione nel C++ di questa nuova feature, come al solito derivata dalle Boost C++ Libs (e già inclusa nel cosiddetto Technical Report 1 dello standard C++), permette di superare almeno in parte i limiti della introspection del C++.

Codice d’esempio

Nel codice di esempio che segue mostro una semplice funzione-template che restituisce tutti i tratti di un specifico tipo.

I tratti possono essere divisi in due categorie, “unari” e “binari”: i primi permettono perlopiù di verificare se un tipo ha una certa caratteristica o meno, mentre i secondi permettono di verificare le relazioni fra due tipi (es: se una classe deriva da un’altra).

Ho suddiviso i tratti, recuperati dal draft attuale dello standard in due liste e per espanderle sfrutto un’apposita piccola XMacro.

In una prossima puntata vedremo i trait usati più seriamente… ^^

Nel frattempo, spero che il codice sia comprensibile.

Ciau!

/**
 *	FILE      : TypeAnalyzer.cpp
 *	AUTHOR    : Gian Paolo "JP" Ghilardi (http://rejex.wordpress.com)
 *	LICENSE   : released under the terms of GPL v2.0 ("only")
 *	COMPILE   : g++ -Wall -Winline -pedantic -std=c++0x
 *	            TypeAnalyzer.cpp -o TypeAnalyzer
 *	PURPOSE   : simple C++0x example showing new type traits facility.
 *
 *	TESTED ON :
 *	- Windows XP, x86 32-bit, G++ 4.4.0
 *
 *	REFERENCES:
 *	[1]: http://en.wikipedia.org/wiki/C%2B%2B0x#Type_traits_for_metaprogramming
 *	[2]: http://en.wikipedia.org/wiki/C%2B%2B0x#Rvalue_reference_and_move_semantics
 *	[3]: http://en.wikipedia.org/wiki/C_preprocessor#X-Macros
 *	[4]: http://en.wikipedia.org/wiki/C_preprocessor#Quoting_macro_arguments
 *	[5]: http://en.wikipedia.org/wiki/RTTI
 */

#include "TypeAnalyzer.h"

using namespace std;

// two simple structs...
struct A {};
struct B: A {};

int main(int argc, char **argv)
{
	cout << "\nC++0x EXAMPLE:" << endl;
	cout << "Simple example showing C++0x type traits facility" << endl;

	printTraits<A>();
	printTraits<A&>();
	printTraits<A&&>(); // rvalue reference, [2]
	printTraits<A*>();
	printTraits<A, A>();
	printTraits<A, B>();

	return EXIT_SUCCESS;
}
/**
 *	FILE      : TypeAnalyzer.h
 *	AUTHOR    : Gian Paolo "JP" Ghilardi (http://rejex.wordpress.com)
 *	LICENSE   : released under the terms of GPL v2.0 ("only")
 *	COMPILE   : g++ -Wall -Winline -pedantic -std=c++0x
 *	            TypeAnalyzer.cpp -o TypeAnalyzer
 *
 *  NOTE      : for more info, please see file TypeAnalyzer.cpp
 */

#ifndef TYPETRAITS_H_
#define TYPETRAITS_H_

#ifdef __STRICT_ANSI__ // to avoid a MinGW G++ 4.4.0 bug ("swprintf undeclared...")
	#undef __STRICT_ANSI__
	#include <cstdlib>
	#include <iostream>
	#define __STRICT_ANSI__
#else
	#include <cstdlib>
	#include <iostream>
#endif

#include <typeinfo>
#include <type_traits>

using namespace std;

#define TO_STRING(trait) #trait // "Stringizing Operator" [4]

/*
   list of C++0x unary type traits

   Note #1: not all traits are listed here.
            The current C++0x draft (March 2009)
            includes more traits. For more info,
            please refer to that draft:
            "meta.type.synop", $20.6.2.

   Note #2: each trait is wrapped to be used
            via XMacro [4]
 */
#define UNARY_TRAITS_LIST \
	X(is_void); \
	X(is_integral); \
	X(is_floating_point); \
	X(is_array); \
	X(is_pointer); \
	X(is_lvalue_reference); \
	X(is_rvalue_reference); \
	X(is_member_object_pointer); \
	X(is_member_function_pointer); \
	X(is_enum); \
	X(is_union); \
	X(is_class); \
	X(is_function); \
	X(is_reference); \
	X(is_arithmetic); \
	X(is_fundamental); \
	X(is_object); \
	X(is_scalar); \
	X(is_compound); \
	X(is_member_pointer); \
	X(is_const); \
	X(is_volatile); \
	X(is_pod); \
	X(is_empty); \
	X(is_polymorphic); \
	X(is_abstract); \
	X(has_trivial_default_constructor); \
	X(has_trivial_copy_constructor); \
	X(has_trivial_assign); \
	X(has_trivial_destructor); \
	X(has_nothrow_default_constructor); \
	X(has_nothrow_copy_constructor); \
	X(has_nothrow_assign); \
	X(has_virtual_destructor); \
	X(is_signed); \
	X(is_unsigned);
    // Unary traits actually not supported by g++/libstdc++:
	// - X(is_trivial);
    // - X(is_standard_layout);

/*
   list of C++0x binary type traits
 */
#define BINARY_TRAITS_LIST \
	X(is_same); \
	X(is_base_of); \
	X(is_convertible);

// Prints valid unary type traits of a type
template <typename T>
inline void printTraits()
{
	cout << "\nTraits of type '" << typeid(T).name() << "':" << endl;

	// Define the Xmacro to expand the list of unary type traits [4]
	#define X(trait) if(trait<T>::value) \
						cout << "- " << TO_STRING(trait) << endl;
	UNARY_TRAITS_LIST
	#undef X
}

// Prints valid binary type traits of a type compared to another type
template <typename T, typename C>
inline void printTraits()
{
	cout << "\nTraits of type '" << typeid(T).name() \
	     << "' compared to type '" << typeid(C).name() << "'" << endl;

	// Define the Xmacro to expand the list of binary type traits [4]
	#define X(trait) if(trait<T, C>::value) \
						cout << "- " << TO_STRING(trait) << endl;
	BINARY_TRAITS_LIST
	#undef X
}
#endif /* TYPETRAITS_H_ */

Il codice in esecuzione

Questo è l’output del programma in esecuzione…

TypeAnalyzer (C++0x)

  1. 24 Giugno 2009 alle 12:50 | #1

    Trovo interessante come sia possibile comparare i trait tra due tipi …

  2. jp
    24 Giugno 2009 alle 14:36 | #2

    Già, è una cosa stupenda considerato poi che è sempre a disposizione… :D

  1. No trackbacks yet.