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

时间:2015-12-22 19:56:16

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

在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中进行重构?

1 个答案:

答案 0 :(得分:16)

您正在使用CRTP; LocateFunctions使用AA<int>)的不完全专门化进行实例化,因此访问该专业化的成员会产生相当误导性的错误消息(&#34; no ... named ... in ......&#34;而不是&#34; ......不完整&#34;)。但是,在您的示例中,函数temploid get_it(如果有的话)A<int>确实定义后实例化,使 typename -specifier 格式良好。

至于解决方法,尝试达到类似的效果,例如:通过

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。