如何使包含的类型与另一个模板类型相同?

时间:2017-06-19 22:35:26

标签: c++ templates

对于下面的简化代码片段:

template <typename T>
struct LinkedList {
    struct Node {
        explicit Node(const T& tdata) :
            next{nullptr}, data{std::make_shared<T>(tdata)} {}
        std::unique_ptr<Node> next;
        std::shared_ptr<T> data;
    };
    std::unique_ptr<Node> head;
};

我想要一个std::queue<T>,其中T与LinkedList::Node::data的类型相同。

以下显式定义有效:

template <typename T> using SPQ
    = std::queue<std::shared_ptr<T>>; // WORKS

但是以下所有内容都无法在couldn't infer template argument 'T'的调用网站上进行编译:

template <typename T> using SPQ
    = std::queue<typename std::common_type<decltype(LinkedList<T>::Node::data)>::type>; // FAIL!

template <typename T> using SPQ
    = typename std::template queue<decltype(LinkedList<T>::Node::data)>; // FAIL!

template <typename T> using SPQ
    = std::queue<decltype(LinkedList<T>::Node::data)>; // FAIL!

e.g。致电网站代码:

template <typename T>
void _Walk(const typename LinkedList<T>::Node& node, SPQ<T>& result) {
    result.emplace(node.data);
    const auto& next = node.next;
    if (next) {
        _Walk(*next, result);
    }
}

template <typename T>
SPQ<T> Walk(const LinkedList<T>& ll) {
    SPQ<T> result;

    const auto& head = ll.head;
    result.emplace(head->data);
    const auto& next = head->next;
    if (next) {
        _Walk(*next, result);
    }

    return result;
}

LinkedList<int64_t> _MakeLL() {
    int64_t rootData = 0;
    LinkedList<int64_t> ll;
    ll.head = std::make_unique<LinkedList<int64_t>::Node>(rootData);
    ll.head->next = std::make_unique<LinkedList<int64_t>::Node>(1);
    ll.head->next->next = std::make_unique<LinkedList<int64_t>::Node>(2);
    ll.head->next->next->next = std::make_unique<LinkedList<int64_t>::Node>(4);

    return ll;
}

template <typename T>
void _PrintResult(SPQ<T>& result, const std::string& msg) {
    std::cout << msg;
    while (result.size()) {
        std::cout << *result.front() << ", ";
        result.pop();
    }
    std::cout << '\n';
}

void Test() {
    auto ll = _MakeLL();
    auto result = Walk(ll);
    _PrintResult(result, "Walking: ");
}


int main(int /*argc*/, char * /*argv*/[]) {
    Test();

    std::cout.flush();

    return 0;
}

使用clang++ -std=c++14编译会导致以下错误:

infer-templ-arg.cpp|80 col 2| error: no matching function for call to '_PrintResult'
||         _PrintResult(result, "Walking: ");
||         ^~~~~~~~~~~~
infer-templ-arg.cpp|68 col 6| note: candidate template ignored: couldn't infer template argument 'T'
|| void _PrintResult(SPQ<T>& result, const std::string& msg) {
||      ^
infer-templ-arg.cpp|50 col 3| error: no matching function for call to '_Walk'
||                 _Walk(*next, result);
||                 ^~~~~
infer-templ-arg.cpp|79 col 16| note: in instantiation of function template specialization 'Walk<long>' requested here
||         auto result = Walk(ll);
||                       ^
infer-templ-arg.cpp|34 col 6| note: candidate template ignored: couldn't infer template argument 'T'
|| void _Walk(const typename LinkedList<T>::Node& node, SPQ<T>& result) {
||      ^
|| 2 errors generated.

使用g ++ 7.1.0进行编译会导致类似的错误。

那么,是否可以使队列元素与LinkedList<T>::Node::data的类型相同,而不是明确地声明它?如果是这样,我将如何实现这一目标?

0 个答案:

没有答案