如果
int64_t
为 true,我会尝试返回 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 );
}
您可以使用
std::enable_if
:
template<class T, typename std::enable_if<std::is_integral<T>::value, int>::type = 0>
int64_t to_int64t( const T& t )
{
return t;
}
template<class T, typename std::enable_if<!std::is_integral<T>::value, int>::type = 0>
int64_t to_int64t( const T& t )
{
return t.to_int64t();
}
从 C++17 开始,您可以使用
if constexpr
:
template<class T>
int64_t to_int64t( const T& t )
{
if constexpr (std::is_integral_v<T>)
return t;
else
return t.to_int64t();
}