Reputation: 1440
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).
Upvotes: 7
Views: 685
Reputation: 237
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
Upvotes: 1