2015-07-28 9 views
6

Il seguente codice non riesce a compilare a causa di error: redefinition of ‘template<class Integer, class> void func(Integer)’Perché questa funzione non può essere sovraccaricata con una firma chiaramente diversa?

#include <iostream> 
#include <type_traits> 

template<typename Float, typename = typename 
std::enable_if<std::is_floating_point<Float>::value>::type> 
void func(Float floatVal) 
{ 
    std::cerr << "float: " << floatVal << "\n"; 
} 

template<typename Integer, typename = typename 
std::enable_if<std::is_integral<Integer>::value>::type> 
void func(Integer integer) 
{ 
    std::cerr << "integral: " << integer << "\n"; 
} 

int main() 
{ 
    func(32.4246); 
    func(144532); 
} 

Ma le due funzioni saranno chiaramente avere diverse firme sul modello di istanza. Quindi, perché non è possibile compilare questo?

Si prega di notare: Io faccio sapere come risolvere questo problema: semplicemente aggiungendo un altro parametro modello fittizio per una delle funzioni, per esempio typename=void, lavorerà, come qui

template<typename Integer, typename dummy=void, typename = typename 
std::enable_if<std::is_integral<Integer>::value>::type> 
void func(Integer integer){} 

Ma la domanda è il motivo per cui devo fare questo?

+0

il problema è che si sta impostando per default il tipo di modello per il secondo modello arg. – AndyG

+0

Non è possibile fornire un altro parametro di default del modello ad altre dichiarazioni nello stesso ambito. – edmz

risposta

5

N4527 § 1.3.19 [ defns.signature.templ]

firma

< funzione template> nome, elenco tipo di parametro (8.3.5), allegando namespace (se presente), tipo di ritorno, e modello di lista di parametri argomento di un template

Il valore di default è non parte della firma di un modello di funzione.

4

È possibile modificare std::enable_if<...>::type come tipo di ritorno della funzione. Per quanto ne so non puoi passarlo al tipo di un altro parametro template.

#include <iostream> 
#include <type_traits> 

template<typename Float> 
typename std::enable_if<std::is_floating_point<Float>::value>::type 
func(Float floatVal) 
{ 
    std::cerr << "float: " << floatVal << "\n"; 
} 

template<typename Integer> 
typename std::enable_if<std::is_integral<Integer>::value>::type 
func(Integer integer) 
{ 
    std::cerr << "integral: " << integer << "\n"; 
} 

int main() 
{ 
    func(32.4246); 
    func(144532); 
} 

Live Example

+0

Questo non funzionerà se le funzioni sono costruttori (il mio esempio è stato semplicemente semplificato perché il problema si riproduce con funzioni libere). Inoltre, questo non risponde alla domanda: "perché?". – Ruslan

2

alternativa al sovraccarico sul tipo di ritorno come NathanOliver ha fatto, si può essere un po 'più complicato nei tipi di modello:

template<typename Float, typename std::enable_if<std::is_floating_point<Float>::value>::type* = nullptr> 
void func(Float floatVal) 
{ 
    std::cerr << "float: " << floatVal << "\n"; 
} 

template<typename Integer, typename std::enable_if<!std::is_floating_point<Integer>::value && std::is_integral<Integer>::value>::type* = nullptr> 
void func(Integer integer) 
{ 
    std::cerr << "integral: " << integer << "\n"; 
} 

Live Demo
Si noti che la seconda enable_if per Integer nega esplicitamente il enable_if condizione per Float

Il vantaggio di questo approccio è che le funzioni ancora restituiscono void

e testarlo:

int main() 
{ 
    func(32.4246); 
    func(144532); 
} 

uscita:

float: 32.4246 
integral: 144532 
Problemi correlati