【问题标题】:C++17 dependent name is not a type, works in C++14C++17 依赖名称不是类型,适用于 C++14
【发布时间】:2019-12-07 02:18:49
【问题描述】:

考虑以下代码:

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&lt;T&gt;::alias': dependent name is not a typesyntax error: identifier 'alias'

通常当您得到涉及dependent name 的内容时,这意味着您需要添加typename 关键字,如下例所示(iterator 依赖于std::vector&lt;T&gt;):

template<typename T> 
void bar() {
    /* typename */ std::vector<T>::iterator it;
}

但是,我认为情况并非如此。此外,使用using MyAlias = Example&lt;T, Y&gt;::alias&lt;ExampleA&gt;; 会导致同样的错误。

C++17 中的更改是否使此代码无效,或者这是编译器错误?在 C++17 中我能做些什么来解决这个问题?

【问题讨论】:

  • 为了快速修复,这可能有效:using MyAlias = typename ExampleA::template alias&lt;ExampleA&gt;;
  • 谢谢,编译成功了。我尝试了 typename 前缀并分别添加 ::template 但没有一起添加。知道为什么现在在 C++17 中需要它吗?或者这可能是 C++14 版本的修复?
  • 您的问题是 MSVC 特有的吗?如果是这样,您应该适当地标记您的问题。 MSVC 的解析算法在过去比其他编译器更宽容,这可能只是他们开始对语言规则更加严格。 (此外,无论标准版本如何,GCC 都会拒绝您的代码)
  • 感谢您的提醒。我没有在其他地方测试过,所以我不确定它是否特定于 MSVC,但我继续添加了标签。

标签: c++ templates visual-c++ c++17


【解决方案1】:

MSVC 由于其编译器的实现细节而忽略了消歧器的缺失。

随着编译器的新进步和重新设计,他们现在实现了应有的两阶段名称查找。然而,在实现了这一点后,在某些情况下很难忽略消歧器的缺失。

他们对/permissive- 标志变得更加严格,这是由于他们之前缺乏两阶段名称查找而试图禁用他们的大部分扩展。

你的代码 sn-p 看起来像这样带有消歧义:

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++20 中,许多需要去歧义器的情况现在都是可选的” 为什么?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-01-04
  • 1970-01-01
  • 1970-01-01
  • 2018-06-27
  • 1970-01-01
  • 1970-01-01
  • 2015-09-21
相关资源
最近更新 更多