问题描述
在我的一个库中,我有以下代码(为简洁起见):
namespace memory {
namespace managed {
namespace detail {
template <typename T>
inline T get_scalar_range_attribute(
region_t region,cudaMemRangeAttribute attribute)
{ /* snip */ }
} // namespace detail
struct region_t : public memory::region_t {
// snip
bool is_read_mostly() const
{
return detail::get_scalar_range_attribute<bool>(
*this,cudaMemRangeAttributeReadMostly);
}
// snip
}
} // namespace managed
} // namespace memory
现在,在 Linux 上使用 GCC 和 Clang,这可以正常工作。但是对于 Windows 上的 MSVC 16.8.4,我的一个用户得到:
error : template instantiation resulted in unexpected function type of "__nv_bool
(cuda::memory::managed::region_t,cudaMemRangeAttribute)" (the meaning of a name
may have changed since the template declaration -- the type of the template is "T
(cuda::memory::region_t,cudaMemRangeAttribute)"
我不明白实例化如何导致意想不到的事情,永远。我也没有看到我的一个类名与另一个类名的“名称隐藏”应该如何对模板实例化产生任何影响。
解决方法
(大部分内容归功于@Guillaume Racicot。)
这里的问题是名称查找的时间。
其他编译,当遇到模板声明region_t
时,似乎寻找之前定义的region_t
;找到memory::region_t
;没关系。 (如果我错了,请纠正我)。
然而,MSVC 执行两次查找:一次是在遇到声明+定义时,然后是在实例化时 - 两次都使用不同的上下文。所以,它第一次找到 memory::region_t
;第二次找到memory::managed::region_t
。这是“意外”...
MSVC 的这种行为显然是由于其“许可”编译模式(默认情况下启用)。这有点奇怪,看看在这种情况下它是如何不太宽容的,但事实就是如此。