integral_constant vs constexpr

时间:2017-10-09 16:11:13

标签: c++ c++11 templates

请您解释一下,为什么以下示例中的integral_constant和constexpr方法导致不同的行为?

#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方法https://ideone.com/WQy71r

1
2
2
3

constexpr方法https://ideone.com/wPiM1m

1
1
1
1

如果我从全局范围中删除Logger结构并使用Traits,则两种方法都会给结构(https://ideone.com/WGVuXE https://ideone.com/OpTbDm)中的integral_constant提供相同的结果。

1 个答案:

答案 0 :(得分:0)

这是因为您的IsRawString()声明为非static,并且需要调用类对象。

当编译器尝试生成Logger::Traits<char*>::IndexLogger::Traits<const char*>::Index时,使用 SFINAE http://en.cppreference.com/w/cpp/language/sfinae)并使用constexpr函数拒绝错误的变体。仅生成Traits的{​​{1}}表单。尝试将template<typename Type, typename Enable = void>声明为IsRawString()成员函数