c++ - 如何使用 std::is_integral<> 选择实现?

标签 c++ templates c++11 typetraits

我正在尝试返回 int64_t如果 std::is_integral<>::value是真的。

否则,我想调用 to_int64t()在物体上。

我在下面的尝试失败了,因为不允许函数模板的部分特化。

代码

#include <type_traits>
#include <cstdint>

template<class T,bool is_integral_type>
int64_t to_int64t( const T& t )
{
        return t;
}

template<class T>
int64_t to_int64t<T,std::is_integral<T>::value>( const T& t )
{
        return t;
}

template<class T>
int64_t to_int64t<T,!std::is_integral<T>::value>( const T& t )
{
        return t.to_int64t();
}

int main()
{
        int64_t i = 64;
        auto x = to_int64t( i );
}

最佳答案

函数模板不能部分特化,一般来说,使用函数模板特化不是一个好主意。

实现您想要的一种方法是使用一种称为标签调度的技术,该技术主要包括提供一个转发器函数,该函数根据额外虚拟参数的值选择正确的重载:

#include <type_traits>
#include <cstdint>

template<class T>
int64_t to_int64t( const T& t, std::true_type )
{
    return t;
}

template<class T>
int64_t to_int64t( const T& t, std::false_type )
{
    return t.to_int64t();
}

template<class T>
int64_t to_int64t( const T& t )
{
    return to_int64t(t, std::is_integral<T>());
}

int main()
{
    int64_t i = 64;
    auto x = to_int64t( i );
}

另一种可能性是使用基于std::enable_if 的经典SFINAE 技术。这就是它的样子(注意,从 C++11 开始,函数模板上的默认模板参数是允许的):

#include <type_traits>
#include <cstdint>

template<class T, typename std::enable_if<
    std::is_integral<T>::value>::type* = nullptr>
int64_t to_int64t( const T& t )
{
    return t;
}

template<class T, typename std::enable_if<
    !std::is_integral<T>::value>::type* = nullptr>
int64_t to_int64t( const T& t )
{
    return t.to_int64t();
}

int main()
{
    int64_t i = 64;
    auto x = to_int64t( i );
}

另一种可能性,虽然更冗长,是在 detail 命名空间中定义帮助类模板(可以部分专门化)并提供全局转发器 - 我不会将此技术用于此用途案例,但我展示它是因为它在相关设计情况下可能会派上用场:

#include <type_traits>
#include <cstdint>

namespace detail
{
    template<class T, bool = std::is_integral<T>::value>
    struct helper { };

    template<class T>
    struct helper<T, true>
    {
        static int64_t to_int64t( const T& t )
        {
            return t;
        }
    };

    template<class T>
    struct helper<T, false>
    {
        static int64_t to_int64t( const T& t )
        {
            return t.to_int64t();
        }
    };
}

template<class T>
int64_t to_int64t( const T& t )
{
    return detail::helper<T>::to_int64t(t);
}

int main()
{
    int64_t i = 64;
    auto x = to_int64t( i );
}

关于c++ - 如何使用 std::is_integral<> 选择实现?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15598939/

相关文章:

c++ - 什么时候函数应该使用 cstrings 而不是字符串? (C++)

c++11 在头文件中无法识别

C# 到 C 代码 P/INvoke 多个标准 :string declarations lead to stack corruption

c++ - 如何声明指针成员禁止删除它

c++ - 为什么添加函数参数会导致无法识别 SLOT()?

c++ - 将一个 mpl 序列序列转换成一个 trie

c++在使用串口发送之前将十六进制转换为ASCII

C++11 性能 : Lambda inlining vs Function template specialization

html - Jekyll 中循环计数器的增量

c++ - `Object obj(args...)` 和 `Object obj{args...}` 有什么区别?