2016-02-01 16 views
7

Bir sınıf için bir kurucu oluşturmak istiyorum, herhangi bir integral türünü kullanarak, ancak imzalı ve imzasız arasında ayrım yapın. Bunun sınıfın kendisinde bir şablon olmasını istemiyorum. Aşağıdaki çalışmıyor. Visual Studio sadece argümanların eşleşmeyeceğini söylüyor.imzalı ve imzasız değişkenler için varyantik bir yapıcıyı kullanarak 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

Çalışmıyor mu? Ne yapıyor? :) – erip

+0

'public' anahtar kelimesinin eksikliği, yukarıdaki kodu denerken alacağım ilk hata hakkında en azından bir şey söylüyor ... – skypjack

cevap

5

SFINAE'yi şablona taşımamız gerekiyor. Biz

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); 
} 

kullanırsanız Biz de bunlar varsayılan olarak private olduğu gibi kurucular public yapmak zorunda Live Example

signed 
unsigned 
olsun.

3

sorun türü bir non-deduced context olarak görünür, derleyici std::is_integral<Integral>::value gibi bir şey onu anlamak edemez olmasıdır. Bunun yerine bu deneyin:

#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

Yan not: En kurucular public olarak aksi takdirde nesneleri örneğini olamaz olun.

+0

OP'nin ayrıca ctors' public' :-) yapmak için gerekli olduğunu işaret ederek sneakily kaçındı – AndyG

+0

@AndyG Gerçekten bunu söylemeyi unutmuştum, ama onları 'public' kodumda yaptım;) – vsoftco

+0

Şahsen ben şablon arşivlerinde 'enable_if'ı seçmeyi tercih ederim:' template :: değeri) && (! std :: is_same :: değeri) && (std :: :: değeri is_signed), int> :: türü = 0> şey (T _in) 'ama hepsi aynı – AndyG

İlgili konular