I want to make a constructor for a class, using any integral type, but differentiate between signed and unsigned. I don't want this to be a template on the class itself. The following is not working. Visual Studio is just saying 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
}
};
We need to move the SFINAE into 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
I also had to make the constructors public
as they were private
by default.
The problem is that the type appears in a non-deduced context , so the compiler cannot deduce it from something like std::is_integral<Integral>::value
. Try this 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);
}
Side note: make your constructors public
as otherwise you cannot instantiate your objects.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.