Reputation: 3
I'm unable to have this code running properly on Ubuntu 20.04 (gcc), and I'm only able to have the template deducted for the else branch (integers), ignoring all the deductions for bool, double and std:string
I even tried the std::enable_if but to no avail...
What am I'm missing here?
#include <iostream>
#include <string>
#include <cstdint>
namespace myns
{
using UInt64 = uint64_t;
using Int64 = int64_t;
using UInt32 = uint32_t;
using Int32 = int32_t;
using UInt16 = uint16_t;
using Int16 = int16_t;
using UInt8 = uint8_t;
using Int8 = int8_t;
}
bool function_int (myns::UInt64& i)
{
i = 10;
}
bool function_float (double& d)
{
d = 4.3;
}
bool function_bool (bool& b)
{
b = true;
}
bool function_str(std::string& s)
{
s = "Hello World";
}
template <typename T>
bool function(T&& value)
{
if constexpr (std::is_same_v<T, bool>)
{
std::cout << "Returning bool" << std::endl;
return function_bool (std::forward<T> (value));
}
else if constexpr (std::is_same_v<T, double>)
{
std::cout << "Returning double" << std::endl;
return function_float (std::forward<T> (value));
}
else if constexpr (std::is_same_v<T, std::string>)
{
std::cout << "Returning string" << std::endl;
return function_str (std::forward<T> (value));
}
else
{
std::cout << "Returning integer" << std::endl;
myns::UInt64 val;
auto ret = function_int (val);
value = val;
}
}
using namespace myns;
int main()
{
UInt64 ui64;
Int64 i64;
UInt32 ui32;
Int32 i32;
UInt16 ui16;
Int16 i16;
UInt8 ui8;
Int8 i8;
std::string str;
bool boolean;
double dbl;
function(str);
function(ui64);
function(i64);
function(ui32);
function(i32);
function(ui16);
function(i16);
function(ui8);
function(i8);
function(boolean);
function(dbl);
std::cout << "Uint64: " << ui64 << std::endl;
std::cout << "Int64: " << i64 << std::endl;
std::cout << "UInt32: " << ui32 << std::endl;
std::cout << "Int32: " << i32 << std::endl;
std::cout << "UInt16: " << ui16 << std::endl;
std::cout << "Int16: " << i16 << std::endl;
std::cout << "UInt8: " << ui8 << std::endl;
std::cout << "Int8: " << i8 << std::endl;
std::cout << "String: " << str << std::endl;
std::cout << "bool: " << boolean << std::endl;
std::cout << "double: " << dbl << std::endl;
}
Output:
Returning integer
Returning integer
Returning integer
Returning integer
Returning integer
Returning integer
Returning integer
Returning integer
Returning integer
Returning integer
Returning integer
Uint64: 10
Int64: 10
UInt32: 10
Int32: 10
UInt16: 10
Int16: 10
UInt8:
Int8:
String:
bool: 1
double: 10
I've been banging my head for almost a day with no solutions on site, I even though of giving up and creating a template specialization for all the types, but I this is a lot of code "repetition" that could be all done in a small template
Thanks in advance!
Upvotes: 0
Views: 60
Reputation: 3
Thanks to @cdhowie the proper code should be like the one below
#include <iostream>
#include <string>
#include <cstdint>
namespace myns
{
using UInt64 = uint64_t;
using Int64 = int64_t;
using UInt32 = uint32_t;
using Int32 = int32_t;
using UInt16 = uint16_t;
using Int16 = int16_t;
using UInt8 = uint8_t;
using Int8 = int8_t;
}
bool function_int (myns::UInt64& i)
{
i = 10;
}
bool function_float (double& d)
{
d = 4.3;
}
bool function_bool (bool& b)
{
b = true;
}
bool function_str(std::string& s)
{
s = "Hello World";
}
template <typename T>
bool function(T&& value)
{
if constexpr (std::is_same_v<std::remove_reference_t<T>, bool>)
{
std::cout << "Returning bool" << std::endl;
return function_bool (std::forward<T> (value));
}
else if constexpr (std::is_same_v<std::remove_reference_t<T>, double>)
{
std::cout << "Returning double" << std::endl;
return function_float (std::forward<T> (value));
}
else if constexpr (std::is_same_v<std::remove_reference_t<T>, std::string>)
{
std::cout << "Returning string" << std::endl;
return function_str (std::forward<T> (value));
}
else
{
std::cout << "Returning integer" << std::endl;
myns::UInt64 val;
auto ret = function_int (val);
value = val;
return value;
}
}
using namespace myns;
int main()
{
UInt64 ui64;
Int64 i64;
UInt32 ui32;
Int32 i32;
UInt16 ui16;
Int16 i16;
UInt8 ui8;
Int8 i8;
std::string str;
bool boolean;
double dbl;
// Ignore the return values, this is just for prototyping..
function(str);
function(ui64);
function(i64);
function(ui32);
function(i32);
function(ui16);
function(i16);
function(ui8);
function(i8);
function(boolean);
function(dbl);
std::cout << "Uint64: " << ui64 << std::endl;
std::cout << "Int64: " << i64 << std::endl;
std::cout << "UInt32: " << ui32 << std::endl;
std::cout << "Int32: " << i32 << std::endl;
std::cout << "UInt16: " << ui16 << std::endl;
std::cout << "Int16: " << i16 << std::endl;
std::cout << "UInt8: " << ui8 << std::endl;
std::cout << "Int8: " << i8 << std::endl;
std::cout << "String: " << str << std::endl;
std::cout << "bool: " << boolean << std::endl;
std::cout << "double: " << dbl << std::endl;
}
Upvotes: 0
Reputation: 169008
T
is being deduced as a reference here. For example, when invoked with a double, the argument is double & &&
(which collapses to double &
). T
is double &
, which is not the same thing as double
. std::is_same_v<double &, double>
is indeed false.
One solution would be to remove any reference from T
before checking:
std::is_same_v<std::remove_reference_t<T>, double>
Side note: you have several functions returning bool
but without any return
statement. This causes undefined behavior.
Upvotes: 2