2016-02-01 16 views
7

整数型を使用してクラスのコンストラクタを作成したいが、符号付きと符号なしを区別したい。私はこれをクラス自体のテンプレートにしたくありません。以下は機能しません。 Visual Studioは引数が一致しないと言うだけです。符号付き変数と符号なし変数の可変コンストラクタを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

これは機能しませんか?それは何ですか? :) – erip

+0

'public'キーワードの欠如は、コードを上にしようとするうちに最初のエラーについて何か言います... – skypjack

答えて

5

SFINAEをテンプレートに移動する必要があります。我々は

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

を使用している場合我々は、私はまた、彼らは、デフォルトでprivateあったようにコンストラクタpublicをしなければならなかったLive Example

signed 
unsigned 
を取得します。

3

問題はタイプがnon-deduced contextに表示されていることなので、コンパイラはstd::is_integral<Integral>::valueのようなものから、それを推測することはできません。代わりにこれを試してみてください:

#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

サイドノート:あなたのコンストラクタを作るpublicとしてそうしないと、あなたのオブジェクトをインスタンス化することはできません。

+0

あなたは、OPもctorsをpublicにする必要があることを卑猥に避けました:-) – AndyG

+0

@AndyG私はこれを本当に言及するのを忘れていましたが、私のコードで 'public'にしました;) – vsoftco

+0

個人的には、テンプレート' args: 'template ::値)&& (!のstd :: is_same ::値)&& (STD :: is_signed ::値)、INT> ::タイプ= 0> シング(T _in ) 'しかし、それはすべて同じです – AndyG

関連する問題