Could you please explain, why integral_constant and constexpr approaches in the following example result in different behaviours?
#include <iostream>
using namespace std;
struct Logger
{
// template<typename Type>
// using IsRawString =
// std::integral_constant<bool, std::is_same<const char*, Type>::value || std::is_same<char*, Type>::value>;
template<typename Type>
constexpr bool IsRawString()
{
return std::is_same<const char*, Type>::value || std::is_same<char*, Type>::value;
}
template<typename Type, typename Enable = void>
struct Traits
{
static const int Index = 1;
};
template<typename Type>
struct Traits<Type, std::enable_if_t<IsRawString<Type>()>>
{
static const int Index = 2;
};
template<typename Type>
struct Traits<Type, std::enable_if_t<std::is_pointer<Type>::value && !IsRawString<Type>()>>
{
static const int Index = 3;
};
};
int main()
{
cout << Logger::Traits<int>::Index << endl
<< Logger::Traits<char*>::Index << endl
<< Logger::Traits<const char*>::Index << endl
<< Logger::Traits<void*>::Index << endl;
return 0;
}
integral_constant approach https://ideone.com/WQy71r:
1
2
2
3
constexpr approach https://ideone.com/wPiM1m:
1
1
1
1
If I remove Logger
struct and use Traits
from the global scope, both approaches give the same result as for integral_constant inside struct (https://ideone.com/WGVuXE https://ideone.com/OpTbDm).
Unlike const, constexpr can also be applied to functions and class constructors. constexpr indicates that the value, or return value, is constant and, where possible, is computed at compile time. A constexpr integral value can be used wherever a const integer is required, such as in template arguments and array declarations.
A constexpr integral value can be used wherever a const integer is required, such as in template arguments and array declarations. And when a value can be computed at compile time instead of run time, it can help your program run faster and use less memory.
When its arguments are constexpr values, a constexpr function produces a compile-time constant. When called with non- constexpr arguments, or when its value isn't required at compile time, it produces a value at run time like a regular function.
TL;DR: const applies to the thing left of it, if there's nothing on the left, then it applies to the thing right of it const int *: nothing on the left, so const if for int: a pointer to a constant integer. equivalent to int const *
It happens because your IsRawString()
declared as non static
and it require class object for to be called.
When compiler try to generate Logger::Traits<char*>::Index
and Logger::Traits<const char*>::Index
it use SFINAE(http://en.cppreference.com/w/cpp/language/sfinae) and reject wrong variants with your constexpr function. The first Traits
form with template<typename Type, typename Enable = void>
generates only. Try declare IsRawString()
as static
member function
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With