2016-02-01 24 views
7

Voglio creare un costruttore per una classe, utilizzando qualsiasi tipo di integrale, ma distinguere tra firmato e non firmato. Non voglio che questo sia un modello sulla classe stessa. Quanto segue non funziona. Visual Studio sta solo dicendo che nessun argomento corrisponderà.crea un costruttore variadic per le variabili firmate e non firmate utilizzando enable_if

class Thing{ 
public: 
    template<typename Integral> 
    Thing(
     typename std::enable_if< 
      std::is_integral<Integral>::value && 
      !std::is_same<Integral,bool>::value && 
      std::is_signed<Integral>::value 
      ,Integral 
     >::type num 
    ){ 
     //constructor using signed variable as input 
    } 
    template<typename Integral> 
    Thing(
     typename std::enable_if< 
      std::is_integral<Integral>::value && 
      !std::is_same<Integral,bool>::value && 
      !std::is_signed<Integral>::value//notice this is different 
      ,Integral 
     >::type num 
    ){ 
     //constructor using unsigned variable as input 
    } 
}; 
+1

Non funziona? Che cosa sta facendo? :) – erip

+0

La mancanza della parola chiave 'public' dice almeno qualcosa riguardo al primo errore che otterrò mentre provo il codice sopra ... – skypjack

risposta

5

Abbiamo bisogno di spostare la SFINAE nel modello. Se usiamo

class Thing{ 
public: 
    template<typename Integral, typename std::enable_if< 
      std::is_integral<Integral>::value && 
      !std::is_same<Integral,bool>::value && 
      std::is_signed<Integral>::value 
      ,Integral>::type* = nullptr> // will fail if type does not exist 
    Thing(Integral i) 
//  ^use Integral type here 
    { 
     std::cout << "signed\n"; 
    } 
    template<typename Integral, typename std::enable_if< 
      std::is_integral<Integral>::value && 
      !std::is_same<Integral,bool>::value && 
      !std::is_signed<Integral>::value//notice this is different 
      ,Integral>::type* = nullptr> 
    Thing(Integral i) 
    { 
     std::cout << "unsigned\n"; 
    } 
}; 

int main() 
{ 
    int a = 10; 
    Thing b(a); 
    unsigned int c = 10; 
    Thing d(c); 
} 

Otteniamo

signed 
unsigned 

Live Example

ho dovuto anche fare i costruttori public come erano private per impostazione predefinita.

3

Il problema è che il tipo appare in una non-deduced context, in modo che il compilatore non può dedurre da qualcosa come std::is_integral<Integral>::value. Prova a modificare:

#include <iostream> 
#include <type_traits> 

class Thing{ 
public: 
    template<typename Integral> 
    Thing(Integral num, 
     typename std::enable_if< 
      std::is_integral<Integral>::value && 
      !std::is_same<Integral,bool>::value && 
      std::is_signed<Integral>::value 
      ,Integral 
     >::type* = nullptr 
    ){ 
     std::cout << "signed\n"; 
     //constructor using signed variable as input 
    } 

    template<typename Integral> 
    Thing(Integral num, 
     typename std::enable_if< 
      std::is_integral<Integral>::value && 
      !std::is_same<Integral,bool>::value && 
      !std::is_signed<Integral>::value//notice this is different 
      ,Integral 
     >::type* = nullptr 
    ){ 
     std::cout << "unsigned\n"; 
     //constructor using unsigned variable as input 
    } 
}; 

int main() 
{ 
    int x{}; 
    unsigned int y{}; 
    Thing thing1(x); 
    Thing thing2(y); 
} 

Live on Coliru

Nota a margine: rendere il vostro costruttori public altrimenti non si può istanziare gli oggetti.

+0

Hai evitato di sottolinearti che OP aveva bisogno anche di rendere i medici' pubblici' :-) – AndyG

+0

@AndyG Ho dimenticato di dirlo, ma li ho resi 'public' nel mio codice;) – vsoftco

+0

Personalmente preferirei mettere' enable_if' nel template args: 'template valore) && (! std :: :: is_same valore) && (std :: :: is_signed valore), int> :: type = 0> Thing (_in T) 'ma è lo stesso – AndyG