【发布时间】:2019-06-09 10:42:22
【问题描述】:
#include <cstddef>
template <class T, std::size_t rank_>
struct B { };
template <class T, std::size_t rank_>
struct A {
static constexpr auto rank = rank_;
operator B<T, rank>() noexcept;
};
template <class T, std::size_t rank>
A<T, rank>::operator B<T, rank>() noexcept { return {}; }
注意rank_ 是A 的类模板参数,rank 是A 的成员的编译时常量。
-
rank用于声明转换运算符- g++ 和 clang 编译没有错误。
- MSVC 19.20 提供
unable to match definition to an existing declaration
-
rank_用于转换运算符的声明- 声明从
operator B<T, rank>() noexcept;更改为operator B<T, rank_>() noexcept; - g++ 给
no declaration matches A<T, rank>::operator B<T, rank> - clang 给
out-of-line definition of operator B<type-parameter-0-0, rank> does not match any declaration in A<T, rank_> - MSVC 编译没有错误
- 声明从
- 谁是正确的?
- 什么是解决问题的便携式解决方案?
感谢 Artyer,将运算符定义中的符号名称从 rank 更改为 rank_ 解决了这个问题。这可能是由于名为rank 的模板参数和类成员rank 之间的歧义所致。编译器执行名称查找的方式不同。
【问题讨论】:
-
奇怪的是,如果您在 gcc (
template<class T, std::size_t rank_> A<T, rank_>::operator B<T, rank_>() noexcept { return {}; }) 中将外部定义更改为使用名称rank_,它会起作用 -
@Artyer 保险杠!它也适用于 MSVC,但更改符号名称会阻止错误非常奇怪。不知道重载中
rank成员和rank模板参数是否有冲突。 -
这很可能是符号
rank的冲突。对于A<T, rank>::部分,rank必须是模板参数,因为编译器还不知道成员变量。但是对于::operator B<T, rank>(),那么rank可以是模板参数或成员变量。
标签: c++ visual-c++ g++ clang language-lawyer