我对SFINAE有基本的了解,比如说enable_if有效.我最近遇到了这个答案,我花了一个多小时试图了解它实际上是如何工作无济于事的.
此代码的目标是根据类中是否包含特定成员来重载函数.这是复制的代码,它使用C++ 11:
template <typename T> struct Model
{
vector<T> vertices;
void transform( Matrix m )
{
for(auto &&vertex : vertices)
{
vertex.pos = m * vertex.pos;
modifyNormal(vertex, m, special_());
}
}
private:
struct general_ {};
struct special_ : general_ {};
template<typename> struct int_ { typedef int type; };
template<typename Lhs, typename Rhs,
typename int_<decltype(Lhs::normal)>::type = 0>
void modifyNormal(Lhs &&lhs, Rhs &&rhs, special_) {
lhs.normal = rhs * lhs.normal;
}
template<typename Lhs, typename Rhs>
void modifyNormal(Lhs &&lhs, Rhs &&rhs, general_) {
// do nothing
}
};
Run Code Online (Sandbox Code Playgroud)
对于我的生活,我无法理解这种机制是如何运作的.具体来说,有什么typename int_<decltype(Lhs::normal)>::type = 0帮助我们做,以及为什么我们需要在此方法中使用额外的类型(special_/ general_).
\n\n\n为什么我们在这个方法中需要一个额外的类型(
\nspecial_/ )general_
modifyNormal这些仅用于允许使用不同实现重载函数的目的。它们的特殊之处在于使用 IS-A 关系,因为它继承自. 此外,该函数始终调用采用该类型的重载,请参阅下一部分。special_general_transformmodifyNormalspecial_
\n\n\n对我们有什么
\ntypename int_<decltype(Lhs::normal)>::type = 0帮助
这是一个具有默认值的模板参数。默认值存在,因此transform函数不必指定它,这很重要,因为其他modifyNormal函数没有此模板参数。此外,添加此模板参数只是为了调用 SFINAE。
http://en.cppreference.com/w/cpp/language/sfinae
\n\n\n\n\n当用推导类型替换模板参数失败时,特化将从重载集中丢弃,而不是导致编译错误。
\n
因此,如果发生故障,modifyNormal采用该special_类型的函数将从要考虑的重载集中删除。这只会让modifyNormal函数采用一种general_类型,并且由于special_IS-Ageneral_类型,一切仍然有效。
如果没有发生替换失败,则将使用modifyNormal使用该special_类型的函数,因为它是更好的匹配。
注意:类型general_为a struct,因此默认继承public,允许不使用关键字的IS-A关系public。
编辑:
\n\n\n\n\n您能评论一下我们为什么要使用这种复杂的
\ntypename int_<decltype(Lhs::normal)>::type机制吗?
如上所述,这用于触发 SFINAE 行为。然而,当你分解它时,它并不是很复杂。它的核心是要实例化int_某种类型的结构实例T,并且它定义了一个type数据类型:
int_<T>::type\nRun Code Online (Sandbox Code Playgroud)\n\n由于这是在模板中使用的typename,因此需要添加关键字,请参阅何时需要 \xe2\x80\x9ctypename\xe2\x80\x9d 关键字?。
typename int_<T>::type\nRun Code Online (Sandbox Code Playgroud)\n\n最后,用于实例化int_结构的实际类型是什么?这是由 确定的decltype(Lhs::normal),它报告 的类型Lhs::normal。如果类型Lhstype 有normal数据成员,那么一切都会成功。但是,如果没有,则表示替换失败,其重要性已在上面进行了解释。
| 归档时间: |
|
| 查看次数: |
323 次 |
| 最近记录: |