调用返回类型不完整的方法和无法解释的模板解决方案



我必须张贴相当多的代码,以解释我的情况。然而,这个问题很简单(参见我文章的最底部和最后一个代码段):

SubscriptProxy::is中,为什么调用this->get_element<Something>(parentElement);时编译,而调用XYZ::get_element<Something>(parentElement);时不编译?


File Element.hpp

class Element{};

File HelperFunctions.hpp:

#include "Element.hpp"
namespace XYZ {
    class Something;
    template<typename T>
    T get_element(Element* e) {
    }
    template<>
    Something get_element(Element* e);
}

File HelperFunctions.cpp:

#include "HelperFunctions.hpp"
#include "Something.hpp"
namespace XYZ {
    template<>
    Something get_element(Element* e) {
       // Convert Element to Something somehow
       return Something{};
    }
}

File SubscriptProxy.hpp:

#include "HelperFunctions.hpp"
namespace XYZ {
    class Something;
    template<typename C, typename D, typename E>
    class SubscriptProxy {
        C m_parent;
        E m_index; 
        template<typename T>
        T get_element(Element* e) const {
            return XYZ::get_element<T>(e); // call helper function
        }
        template<typename T>
        bool is(int index, Element*& e) const noexcept {
            Element* parentElement;
            if (!m_parent.template is<Something>(m_index, parentElement)) {
                return false;
            }
            auto d = this->get_element<Something>(parentElement);
            return d.template is<T>(index, e);
        }
    };
}

然后是Something.hppSomething.cpp。它包含一个返回SubscriptProxy实例的操作符:

#include "SubscriptProxy.hpp"
#include "HelperFunctions.hpp"
namespace XYZ {
    class Something {
        SubscriptProxy<Something, Something, int> operator[] (int index) const noexcept;
    };
}

File Something.cpp:

#include "Something.hpp"
namespace XYZ {
SubscriptProxy<Something, Something, int> Something::operator[] (int index) const noexcept {
    return SubscriptProxy<Something, Something, int>{};
}

编译和工作正常。

然而,如果我改变SubscriptProxy::is方法的实现如下:

        template<typename T>
        bool is(int index, Element*& e) const noexcept {
            Element* parentElement;
            if (!m_parent.template is<Something>(m_index, parentElement)) {
                return false;
            }
            auto d = XYZ::get_element<Something>(parentElement);
            return d.template is<T>(index, e);
        }

调用'get_element'时返回不完整类型'Something'.

为什么?

有两阶段的名称查找来检查模板的错误:

  • 一个用于任何模板参数,所以编译器只检查非依赖的代码。
  • 一个实例化(所以所有参数都是固定的)。

auto d = XYZ::get_element<Something>(parentElement);现在不再依赖于模板,因此编译器可能会为此提供错误。

this->get_element,它取决于this是模板

最新更新