Create a constructor variable for signed and unsigned variables using enable_if

I want to create a constructor for a class using any integral type, but I distinguish between signed and unsigned. I do not want this to be a template for the class itself. The following does not work. Visual Studio simply says that no arguments will match.

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 } }; 
+7
c ++ templates sfinae enable-if
source share
2 answers

We need to move SFINAE to the template. If we use

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

We get

 signed unsigned 

Living example

I also had to create public default private constructors.

+5
source share

The problem is that the type appears in a non-deducible context , so the compiler cannot deduce it from something like std::is_integral<Integral>::value . Try instead:

 #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

Side note: create your public constructors, because otherwise you will not be able to instantiate your objects.

+3
source share

All Articles