NuPagadi
NuPagadi

Reputation: 1440

integral_constant vs constexpr

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

Answers (1)

Sergei_Ivanov
Sergei_Ivanov

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

Related Questions