问题
考虑一下这个代码(
live version
),在这里我已经声明了
struct S
Use
哪个ODR使用它。
S
之后
函数,但在任何
.
struct S;
template<typename T> void Use(S& s, const T& t) { // ODR-use S
s.Use(t); // error: member access into incomplete type 'S'
}
struct S {
template<typename T> void Use(const T&) { }
};
int main() {
auto s = S{}; Use(s, 2); // Instantiation of Use<...>
}
这不会编译,因为显然,S的定义对
功能。
理论基础
基于我对函数模板的理解
§13.9.1 of the latest working draft
这不应该是个问题,因为当函数模板被实例化时,所有类型都被完全定义。
不过,在我看来,所有依赖类型都可以访问实例化时可用的定义,而非依赖类型将使用函数定义中可用的版本。不幸的是,我在定义这种行为的标准中找不到相应的段落。
解决问题
为了解决这个问题,我可以使用IIFE“刷新”当前的定义:
// This is OK:
template<typename T> void Use(S& s, const T& t) {
[&](auto& s_) { s_.Use(t); }(s);
}
// This is also OK:
template<typename T, typename SS = S> void Use(SS& s, const T& t) {
s.Use(t);
}
所以现在我想知道,为什么实例化的模板不总是能够访问任何类型的最新定义,而不仅仅是依赖类型?如上所示,您可以使用立即计算的lambda来强制编译器更新任何类型—那么为什么这不是自动完成的呢?