专门化模板成员函数 [SFINAE]
specialize template member function [SFINAE]
基于this问题和"Dave"提供的答案,如何专门处理非整数类型的情况来处理类型QDate
(用于Qt用于处理与日期相关的任务)?
我要专精的函数是:
void extract(const std::string str)
{
std::bitset<sizeof(T) * CHAR_BIT> bs(str.substr(m_start, m_len));
m_data = static_cast<T>(bs.to_ulong());
}
将 1 和 0 的 std::string
提供给此函数,然后根据开始和长度,我需要将其转换为实例化包含此函数的模板 class 的类型。当类型不是整数或无法使用 std::bitset
.
生成时,它没有意义
我不确定我是否完全理解您的用例,但我认为它与此类似
template<typename T>
struct foo
{
T m_data;
// others ...
void extract(const std::string str)
{
std::bitset<sizeof(T) * CHAR_BIT> bs(str.substr(m_start, m_len));
m_data = static_cast<T>(bs.to_ulong());
}
};
但是当 foo
用 QDate
实例化时,您希望 extract
做一些不同的事情。有几种不同的方法可以完成这项工作,SFINAE 就是其中之一。
但是您不能简单地将 enable_if
表达式附加到 extract
,因为要使 SFINAE 正常工作,替换失败需要在直接上下文中发生,而 T
是 已知 到 foo<T>::extract
被实例化。因此,向默认为 T
.
的 extract
添加一个虚拟模板参数
template<typename U=T>
typename std::enable_if<std::is_same<U, QDate>::value>::type
extract(const std::string str)
{
// this will be used when T=QDate
}
template<typename U=T>
typename std::enable_if<!std::is_same<U, QDate>::value>::type
extract(const std::string str)
{
// this will be used when T!=QDate
}
如果 extract
是唯一改变行为的东西,那么实现此目的的另一种方法是将所有通用功能移动到另一个 class,foo
将从中继承。
template<typename T>
struct foo_base
{
// common functionality
};
template<typename T>
struct foo : foo_base<T>
{
void extract(const std::string str)
{
std::bitset<sizeof(T) * CHAR_BIT> bs(str.substr(m_start, m_len));
m_data = static_cast<T>(bs.to_ulong());
}
};
// Specialization for QDate
template<>
struct foo<QDate> : foo_base<QDate>
{
void extract(const std::string str)
{
// QDate specific functionality
}
};
基于this问题和"Dave"提供的答案,如何专门处理非整数类型的情况来处理类型QDate
(用于Qt用于处理与日期相关的任务)?
我要专精的函数是:
void extract(const std::string str)
{
std::bitset<sizeof(T) * CHAR_BIT> bs(str.substr(m_start, m_len));
m_data = static_cast<T>(bs.to_ulong());
}
将 1 和 0 的 std::string
提供给此函数,然后根据开始和长度,我需要将其转换为实例化包含此函数的模板 class 的类型。当类型不是整数或无法使用 std::bitset
.
我不确定我是否完全理解您的用例,但我认为它与此类似
template<typename T>
struct foo
{
T m_data;
// others ...
void extract(const std::string str)
{
std::bitset<sizeof(T) * CHAR_BIT> bs(str.substr(m_start, m_len));
m_data = static_cast<T>(bs.to_ulong());
}
};
但是当 foo
用 QDate
实例化时,您希望 extract
做一些不同的事情。有几种不同的方法可以完成这项工作,SFINAE 就是其中之一。
但是您不能简单地将 enable_if
表达式附加到 extract
,因为要使 SFINAE 正常工作,替换失败需要在直接上下文中发生,而 T
是 已知 到 foo<T>::extract
被实例化。因此,向默认为 T
.
extract
添加一个虚拟模板参数
template<typename U=T>
typename std::enable_if<std::is_same<U, QDate>::value>::type
extract(const std::string str)
{
// this will be used when T=QDate
}
template<typename U=T>
typename std::enable_if<!std::is_same<U, QDate>::value>::type
extract(const std::string str)
{
// this will be used when T!=QDate
}
如果 extract
是唯一改变行为的东西,那么实现此目的的另一种方法是将所有通用功能移动到另一个 class,foo
将从中继承。
template<typename T>
struct foo_base
{
// common functionality
};
template<typename T>
struct foo : foo_base<T>
{
void extract(const std::string str)
{
std::bitset<sizeof(T) * CHAR_BIT> bs(str.substr(m_start, m_len));
m_data = static_cast<T>(bs.to_ulong());
}
};
// Specialization for QDate
template<>
struct foo<QDate> : foo_base<QDate>
{
void extract(const std::string str)
{
// QDate specific functionality
}
};