tipos template plantillas funciones ats c++ templates

plantillas - template en c++ pdf



Argumentos de plantilla predeterminados para plantillas de funciones (5)

En Windows, con todas las versiones de Visual Studio, puede convertir este error ( C4519 ) en una advertencia o deshabilitarlo de esta manera:

#ifdef _MSC_VER #pragma warning(1 : 4519) // convert error C4519 to warning // #pragma warning(disable : 4519) // disable error C4519 #endif

Ver más detalles C4519 .

¿Por qué los argumentos de plantilla predeterminados solo se permiten en plantillas de clase? ¿Por qué no podemos definir un tipo predeterminado en una plantilla de función miembro? Por ejemplo:

struct mycclass { template<class T=int> void mymember(T* vec) { // ... } };

En cambio, C ++ obliga a que los argumentos de plantilla predeterminados solo se permitan en una plantilla de clase.


Hasta ahora, todos los ejemplos ofrecidos de parámetros de plantilla predeterminados para plantillas de funciones se pueden hacer con sobrecargas.

AraK:

struct S { template <class R = int> R get_me_R() { return R(); } };

podría ser:

struct S { template <class R> R get_me_R() { return R(); } int get_me_R() { return int(); } };

Mío:

template <int N = 1> int &increment(int &i) { i += N; return i; }

podría ser:

template <int N> int &increment(int &i) { i += N; return i; } int &increment(int &i) { return increment<1>(i); }

litb:

template<typename Iterator, typename Comp = std::less<Iterator> > void sort(Iterator beg, Iterator end, Comp c = Comp())

podría ser:

template<typename Iterator> void sort(Iterator beg, Iterator end, std::less<Iterator> c = std::less<Iterator>()) template<typename Iterator, typename Comp > void sort(Iterator beg, Iterator end, Comp c = Comp())

Stroustrup:

template <class T, class U = double> void f(T t = 0, U u = 0);

Podría ser:

template <typename S, typename T> void f(S s = 0, T t = 0); template <typename S> void f(S s = 0, double t = 0);

Lo cual probé con el siguiente código:

#include <iostream> #include <string> #include <sstream> #include <ctype.h> template <typename T> T prettify(T t) { return t; } std::string prettify(char c) { std::stringstream ss; if (isprint((unsigned char)c)) { ss << "''" << c << "''"; } else { ss << (int)c; } return ss.str(); } template <typename S, typename T> void g(S s, T t){ std::cout << "f<" << typeid(S).name() << "," << typeid(T).name() << ">(" << s << "," << prettify(t) << ")/n"; } template <typename S, typename T> void f(S s = 0, T t = 0){ g<S,T>(s,t); } template <typename S> void f(S s = 0, double t = 0) { g<S,double>(s, t); } int main() { f(1, ''c''); // f<int,char>(1,''c'') f(1); // f<int,double>(1,0) // f(); // error: T cannot be deduced f<int>(); // f<int,double>(0,0) f<int,char>(); // f<int,char>(0,0) }

El resultado impreso coincide con los comentarios de cada llamada a f, y la llamada comentada no se puede compilar como se esperaba.

Por lo tanto, sospecho que los parámetros de la plantilla por defecto "no son necesarios", pero probablemente solo en el mismo sentido en que los argumentos de la función por defecto "no son necesarios". Como indica el informe de defectos de Stroustrup, la adición de parámetros no deducidos fue demasiado tarde para que alguien se dé cuenta y / o realmente aprecie que hizo que los valores predeterminados sean útiles. Entonces, la situación actual está en efecto basada en una versión de plantillas de funciones que nunca fue estándar.


Lo que uso es el siguiente truco:

Digamos que quieres tener una función como esta:

template <typename E, typename ARR_E = MyArray_t<E> > void doStuff(ARR_E array) { E one(1); array.add( one ); }

No se te permitirá, pero lo hago de la siguiente manera:

template <typename T> struct MyArray_t { void add(T i) { // ... } }; template <typename E, typename ARR_E = MyArray_t<E> > class worker { public: /*static - as you wish */ ARR_E* parr_; void doStuff(); /* do not make this one static also, MSVC complains */ }; template <typename E, typename ARR_E> void worker<E, ARR_E>::doStuff() { E one(1); parr_->add( one ); }

Así que de esta manera puedes usarlo así:

MyArray_t<int> my_array; worker<int> w; w.parr_ = &arr; w.doStuff();

Como podemos ver, no es necesario establecer explícitamente un segundo parámetro. Tal vez sea útil para alguien.


Para citar plantillas de C ++: la guía completa (página 207):

Cuando las plantillas se agregaron originalmente al lenguaje C ++, los argumentos explícitos de la plantilla de función no fueron una construcción válida. Los argumentos de la plantilla de función siempre deben ser deducibles de la expresión de llamada. Como resultado, no parecía existir una razón convincente para permitir los argumentos de la plantilla de función predeterminada porque el valor deducido siempre anularía el valor predeterminado.


Tiene sentido dar argumentos de plantilla por defecto. Por ejemplo, podría crear una función de clasificación:

template<typename Iterator, typename Comp = std::less< typename std::iterator_traits<Iterator>::value_type> > void sort(Iterator beg, Iterator end, Comp c = Comp()) { ... }

C ++ 0x los presenta a C ++. Vea este informe de defectos de Bjarne Stroustrup: Argumentos de plantilla predeterminados para plantillas de funciones y lo que dice

La prohibición de los argumentos de plantilla predeterminados para las plantillas de funciones es un remanente mal concebido del tiempo en que las funciones independientes se trataron como ciudadanos de segunda clase y requirió que todos los argumentos de la plantilla se deduzcan de los argumentos de la función en lugar de especificados.

La restricción obstaculiza seriamente el estilo de programación al hacer innecesariamente funciones independientes diferentes de las funciones de miembros, lo que hace más difícil escribir código de estilo STL.