简体   繁体   English

在C ++ 11中确定泛型返回类型时出错

[英]error determining a generic return type in C++11

In the context of a C++14 application, I use a scheme which could be resumed as follows (minimal reproducible test): 在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;
}

This approach compiles and runs perfectly in C++14, with GCC and Clang compilers. 这种方法在C ++ 14中使用GCC和Clang编译器进行编译和运行。

Now I want migrate my application to Windows and for that I'm using MinGW. 现在我想将我的应用程序迁移到Windows,为此我正在使用MinGW。 Unfortunately, its latest version brings GCC 4.9 which does not compile C++14. 不幸的是,它的最新版本带来了GCC 4.9,它不能编译C ++ 14。 That does not seem like a serious problem because I can rewrite the C++14 constructs in C++11. 这似乎不是一个严重的问题,因为我可以在C ++ 11中重写C ++ 14结构。 So, I rewrite the get_it() method as follows: 所以,我重写了get_it()方法,如下所示:

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

Unfortunately it does no compile. 不幸的是它没有编译。 Both compilers produce the following error: 两个编译器都会产生以下错误:

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

I also tried: 我也尝试过:

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

but I get exactly the same error. 但我得到完全相同的错误。

Since two compilers fail to recognize the type of return, I suppose it is impossible to determine it. 由于两个编译器无法识别返回类型,我认为无法确定它。 But I do not really know why. 但我真的不知道为什么。

Could someone please explain me why not compile and eventually a way for refactoring in C++11 that compiles? 有人可以解释一下为什么不编译并最终在C ++ 11中编译重构的方法?

You're using CRTP; 你正在使用CRTP; LocateFunctions is instantiated with an incomplete specialization of A ( A<int> ), hence accessing that specialization's members gives the rather misleading error message ("no … named … in …" instead of "… is incomplete"). LocateFunctions实例化了AA<int> )的不完全LocateFunctions化,因此访问该特化的成员会给出相当误导性的错误消息(“no ... named ... in ...”而不是“... is incomplete”)。 However, in your example the function temploid get_it is only (if ever) instantiated after A<int> is indeed defined , making the typename-specifier well-formed. 但是,在您的示例中,函数temploid get_it仅在确实)定义了A<int>之后进行实例化 ,使得typename-specifier格式正确。

As for a workaround, try to achieve a similar effect, eg via 至于解决方法,尝试实现类似的效果,例如通过

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 with GCC 4.9. GCC 4.9 演示

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM