C++ 如何使用decltype作为模板化类的返回类型的模板参数?

C++ 如何使用decltype作为模板化类的返回类型的模板参数?,c++,templates,c++11,decltype,C++,Templates,C++11,Decltype,请参阅下面的代码 template <typename T> struct Node { T data; Node<T>* left; Node<T>* right; Node (T d, Node<T>* l = nullptr, Node<T>* r = nullptr) : data(d), left(l), right(r) {} };

请参阅下面的代码

    template <typename T> 
    struct Node
    {
      T data;
      Node<T>* left;
      Node<T>* right;

      Node (T d, Node<T>* l = nullptr, Node<T>* r = nullptr) : data(d), left(l), right(r) {}
    };

    template <typename ItType>
    auto buildBinaryTree (ItType start, ItType end) -> Node<decltype(*start)>* // doesn't like this line
    {
      // implementation removed for simplicity of post as the signature is the issue
    }

    template <typename T> 
    Node<T>* buildBinaryTree (std::vector<T>& v)
    {
      if  ( v.empty() )
       return nullptr; 

      std::sort(v.begin(), v.end());
      return buildBinaryTree (v.begin(), v.end()); 
    }

int main()
{
  std::vector<int> v { 1,2,3,4,5,6,7,8,9,10 };
  Node<int>* root = buildBinaryTree ( v );
模板
结构体类型
{
T数据;
节点*左;
节点*右;
节点(td,Node*l=nullptr,Node*r=nullptr):数据(d),左(l),右(r){
};
模板
自动构建二进制树(ItType start,ItType end)->Node*//不喜欢这一行
{
//为简化post,删除了实现,因为签名是问题所在
}
模板
节点*buildBinaryTree(std::vector&v)
{
if(v.empty())
返回空ptr;
排序(v.begin(),v.end());
返回buildBinaryTree(v.begin(),v.end());
}
int main()
{
向量v{1,2,3,4,5,6,7,8,9,10};
Node*root=buildBinaryTree(v);
基本上,当我遇到编译错误时,实现以下签名的最佳方法是什么

main.cpp:81:10:错误:无法初始化“Node*”类型的返回对象
具有“Node*”类型的右值
返回buildBinaryTree(v.begin(),v.end());
试试这个:

Node<typename std::decay<decltype(*start)>::type> *
节点*
您需要
#包括


一个更干净的解决方案可能是使用
std::iterator\u traits::value\u type

如果使用标准库的容器,最好的解决方案可能是:

template <typename ItType>
auto buildBinaryTree (ItType start, ItType end) -> Node<typename ItType::value_type>* 
为此(您可能需要
#包括
):

autobuildbinarytree(ItType开始,ItType结束)->Node*
gcc错误消息很清楚:

错误:无法将
节点*
转换为
节点*


显然,您使用的是clang,不幸的是,它没有给出如此明确的错误消息…:(

如果迭代器类型恰好是原始指针,那么
typename ItType::value\u type
解决方案将失败,即使是标准的库容器也允许使用原始指针。您需要额外的间接寻址级别,方法是将其包装在
std::iterator\u traits::value\u type
中,以使代码可移植。@Praetorian非常感谢您将其指向t out;修复了答案中的问题。是的@Ali我在mac上这么做:),我在家使用linux上的gcc:)。这个编译器错误肯定会解决这个问题。再次感谢您的回答。@bjackfly我很高兴它能帮上忙!详细说明一下,问题是
*start
是一个左值,而不是标识符,因此它的
decltype
生成一个引用类型。
decay
删除了引用。感谢@Potatoswatter这有助于澄清这更进一步。谢谢@Kerrek投票回答。
template <typename ItType>
auto buildBinaryTree (ItType start, ItType end) -> Node<typename ItType::value_type>* 
auto buildBinaryTree (ItType start, ItType end) -> Node<decltype(*start)>* 
auto buildBinaryTree (ItType start, ItType end) -> Node<typename std::remove_reference<decltype(*start)>::type>*