【问题标题】:error determining a generic return type in C++11在 C++11 中确定泛型返回类型时出错
【发布时间】:2015-12-22 19:56:15
【问题描述】:

在 C++14 应用程序的上下文中,我使用的方案可以恢复如下(最小可重复测试):

template <class Container>
struct LocateFunctions {    
  auto get_it() const // <-- here is the problem
  {
    auto ret = typename Container::Iterator();
    return ret;
  }
};

template <typename T>
struct A : public LocateFunctions<A<T>> {    
  struct Iterator {};
};

int main() {  
  A<int> a;
}

这种方法可以在 C++14 中完美地编译和运行,使用 GCC 和 Clang 编译器。

现在我想将我的应用程序迁移到 Windows,为此我正在使用 MinGW。不幸的是,它的最新版本带来了 GCC 4.9,它不能编译 C++14。这似乎不是一个严重的问题,因为我可以在 C++11 中重写 C++14 结构。所以,我重写get_it()方法如下:

typename Container::Iterator get_it() const
{ 
  auto ret = typename Container::Iterator();
  return ret;
}

不幸的是它没有编译。两种编译器都会产生以下错误:

error: no type named ‘Iterator’ in ‘struct A<int>’
   typename Container::Iterator get_it() const
                            ^

我也试过了:

auto get_it() const -> decltype(typename Container::Iterator())
{ 
  auto ret = typename Container::Iterator();
  return ret;
}

但我得到完全相同的错误。

由于两个编译器无法识别返回的类型,我想不可能确定它。但我真的不知道为什么。

有人可以解释一下为什么不编译并最终在 C++11 中进行重构的方法可以编译吗?

【问题讨论】:

    标签: c++ templates c++11 c++14 name-lookup


    【解决方案1】:

    您正在使用 CRTP; LocateFunctions 是用不完整的 A (A&lt;int&gt;) 特化实例化的,因此访问该特化的成员会给出相当误导性的错误消息(“no ... named ... in ...”而不是“... is不完整”)。但是,在您的示例中函数 temploid get_it(如果有的话)在确实定义了 A&lt;int&gt; 之后实例化,使得 typename-specifier em> 格式良好。

    至于解决方法,尝试实现类似的效果,例如通过

    template <typename T=Container>
    typename T::Iterator get_it() const
    {
        static_assert(std::is_same<T, Container>{}, "You ain't supposed to supply T!");
        auto ret = typename T::Iterator();
        return ret;
    }
    

    Demo 与 GCC 4.9。

    【讨论】:

    • Temploid ?是这个词吗?
    • @Quentin 是的。它表示模板的非模板成员,受 15 年前打开的某个 DR 影响。
    • 非常感谢 Columbo 的解释、解决方法和版本
    • @lrleon 很高兴我能帮上忙 :-)
    猜你喜欢
    • 2015-05-20
    • 1970-01-01
    • 2012-09-01
    • 1970-01-01
    • 2011-02-24
    • 2011-01-15
    • 1970-01-01
    • 2023-04-07
    • 2014-05-16
    相关资源
    最近更新 更多