我遇到了一个与模板相关的问题,我已经缩小到以下示例(C++17):
template <typename T> struct item {
operator item<const T> () const { return item<const T>(); }
};
void conversionToConstRefWorks (const item<const int> &) { }
template <typename T>
void butNotWhenTemplated (const item<const T> &) { }
int main () {
item<int> i;
item<const int> ci;
// these all compile fine:
conversionToConstRefWorks(ci);
conversionToConstRefWorks(i);
butNotWhenTemplated(ci);
// but this one fails:
butNotWhenTemplated(i);
}
在这个例子中:
- `item` 有一个隐式转换运算符到 `item`,并且 - 在 `conversionToConstRefWorks()` 中转换似乎起作用,但是 - 在 `butNotWhenTemplated()` 中转换被忽略了,在那里一个 `item` 可以很好地传递,但是传递一个 `item` 会导致编译错误。
这个例子的编译失败(GCC 9.3)是:
g++ --std=c++17 -W -Wall -pedantic -Wno-unused-variable const_interop.cpp -o const_interop
const_interop.cpp: In function ‘int main()’:
const_interop.cpp:54:24: error: no matching function for call to ‘butNotWhenTemplated(item<int>&)’
54 | butNotWhenTemplated(i);
| ^
const_interop.cpp:40:6: note: candidate: ‘template<class T> void butNotWhenTemplated(const item<const T>&)’
40 | void butNotWhenTemplated (const item<const T> &) {
| ^~~~~~~~~~~~~~~~~~~
const_interop.cpp:40:6: note: template argument deduction/substitution failed:
const_interop.cpp:54:24: note: types ‘const T’ and ‘int’ have incompatible cv-qualifiers
54 | butNotWhenTemplated(i);
| ^
根本错误似乎是:
我从字面上理解了这句话,但我不明白为什么会发生这种情况。我的期望是,在调用类型“const T”和“int”的cv限定符不兼容
butNotWhenTemplated(i)
时,item<int> :: operator item<const int> () const
转换运算符将被应用,就像在调用conversionToConstRefWorks(i)
时一样,并且T
将选择int
。我的主要问题是:为什么这不编译? 我的另一个问题是:出于本帖子范围之外的原因,
butNotWhenTemplated
必须是一个模板,并且必须对所有item
参数指定<const T>
,而我不能在调用它时显式地指定模板参数。有没有办法在这些约束条件下使其工作?
点此在ideone上查看(GCC 8.3)。
T*
代替了Item<T>
) - ph3rinint *
→int const * const &
转换不是在模板参数内完成的(与Item<T>
→Item<const T>
不同 -- 你的更类似于Item<T>
→const Item<T>
)。例如,T
和const T
是仅在 cv 限定符上有所不同的相同类型,而Item<T>
和Item<const T>
是完全不同的类型,因为模板参数不同,然后一些推导规则让它可以。也许吧。另一方面,我不知道我在说什么。 - Jason C