PDA

View Full Version : [C++] Restringere tipo template (come Java: <T extends Base>)


biowep
14-10-2014, 15:08
Ciao, so che non esiste un modo diretto per poter restringere il tipo che un parametro di un template può diventare. Quello che volevo chiedere è come ci si comporta in questi casi?
Voglio dire, io in java posso definire:
class Classe<T extends Base>{}
Dentro quella classe so che posso sicuramente (senza preoccuparmi di nulla), dato un attributo o una variabile di tipo T chiamare tutti i membri di Base. Certamente se poi vorrò qualcosa in più dovrò verificare il tipo e fare un casting.

In C++ si fa il casting normalmente o si chiamano metodi dati per scontato senza preoccuparsi di quale tipo sia il template? Considerato che il compilatore a volte da informazioni completamente generiche sull'errore commesso e quindi chi userà quel determinato codice potrebbe non capire.

WarDuck
14-10-2014, 19:22
Potresti usare le static_assertion di C++11 insieme ai type traits:


#include <iostream>
#include <type_traits>

class Base
{
public:
virtual void hello() = 0;
};

class Specific : public Base
{
public:
virtual void hello() {
printf("Hello World!\n");
}
};

class Another {
void hello() {
}
};

template<class T>
class Wrapper
{
T object;

public:

Wrapper() {
static_assert(std::is_base_of<Base, T>::value, "T must be a Base type");
}

void hello() {

object.hello();
}
};

int main(void)
{
Wrapper<Another> w; // non compila (se usi Wrapper<Specific> compila)

w.hello();

return 0;
}


Output con Wrapper<Another>:

example.cc: In instantiation of ‘Wrapper<T>::Wrapper() [with T = Another]’:
example.cc:44:22: required from here
example.cc:33:9: error: static assertion failed: T must be a Base type

biowep
14-10-2014, 20:25
Molto interessante, ma rispetto a static_cast, è di molto più inefficiente?
Inoltre, static_assert sarebbe un costrutto del linguaggio che permette di generare un qualsiasi errore nel compilatore in base ad una condizione oppure è pensato per altro?

Grazie per l'aiuto.

WarDuck
15-10-2014, 08:35
Molto interessante, ma rispetto a static_cast, è di molto più inefficiente?
Inoltre, static_assert sarebbe un costrutto del linguaggio che permette di generare un qualsiasi errore nel compilatore in base ad una condizione oppure è pensato per altro?

Grazie per l'aiuto.

Quello che ho riportato sopra è il metodo più sicuro (type safe) in quanto se passi un oggetto che non ha quella classe base non compila ;).

static_assert è una asserzione a compile time, ma la condizione dev'essere appunto verificabile a tempo di compilazione (in C++11 hanno anche introdotto la keyword constexpr che ti può aiutare nel costruire espressioni valutabili a tempo di compilazione).

In realtà anche static_cast dovrebbe fare dei controlli sul tipo a tempo di compilazione (sicuramente più che quelli del cast C classico), però dal mio punto di vista quella sopra è una soluzione più "elegante" :D.