考虑以下代码:
template <typename T>
struct X
{
void foo(){}
};
class Y { };
template <typename T, typename... U>
class Example {
protected:
template <template<typename> typename example_t>
using alias = X<example_t<T>>;
};
template <typename T>
struct ExampleA : public Example<T, Y>
{
using MyAlias = ExampleA::alias<ExampleA>;
};
在 C++14 中,我可以执行以下操作并使其按预期工作:
ExampleA<int>::MyAlias test;
test.foo();
最近升级到 C++17 现在给出警告 'ExampleA<T>::alias': dependent name is not a type
以及syntax error: identifier 'alias'
.
通常当你得到涉及 dependent name
的东西时这意味着您需要添加 typename
关键字如下例( iterator
依赖于 std::vector<T>
):
template<typename T>
void bar() {
/* typename */ std::vector<T>::iterator it;
}
但是,我不认为这里是这种情况。此外,使用 using MyAlias = Example<T, Y>::alias<ExampleA>;
导致相同的错误。
C++17 中的更改是否使此代码无效,或者这是一个编译器错误?我该怎么做才能在 C++17 中解决这个问题?
最佳答案
由于其编译器的实现细节,MSVC 忽略了消歧器的缺失。
随着他们编译器的新进展和重新设计,他们现在实现了他们应该实现的两阶段名称查找。然而,在实现后,在某些情况下真的很难忽略消歧器的缺失。
他们对 /permissive-
标志变得更加严格,这是由于他们之前缺少两阶段名称查找而试图禁用他们的大部分扩展。
您的代码片段看起来像这样带有消歧义器:
template <typename T>
struct ExampleA : public Example<T, Y>
{
using MyAlias = typename ExampleA::template alias<ExampleA>;
};
将其视为升级代码的兼容性和可移植性的机会。
但是对于 C++20,许多需要去歧义器的情况现在是可选的:
template<typename T>
auto wrapper() -> T::type; // no typename!
关于C++17 依赖名称不是类型,适用于 C++14,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57258965/