具有递归大小写结尾的模板语法错误

Template syntax error with end of recursion case

本文关键字:语法 错误 结尾 递归 大小写      更新时间:2023-10-16

有人可以告诉我下面递归专业化结束的语法有什么问题吗? 我以为我遵守了所有规则。

#include <iostream>
template <typename StreamType = std::ostream, StreamType& stream = std::cout>
class StringList {
    template <typename...> class AddStrings;
  public:
    template <typename... Args> void addStrings (Args&&... args) {AddStrings<Args...>()(args...);}
};
template <typename StreamType, StreamType& stream>
template <typename First, typename... Rest>
class StringList<StreamType, stream>::AddStrings<First, Rest...> : AddStrings<Rest...> {
public:
    void operator()(First&& first, Rest&&... rest) {
        // do whatever
        AddStrings<Rest...>::operator()(std::forward<Rest>(rest)...);
    }
};
template <typename StreamType, StreamType& stream>
template <>
class StringList<StreamType, stream>::AddStrings<> {
    friend class StringStreamList;
    void operator()() const {}  // End of recursion.
};
int main() {
    StringList<> stringList;
//  stringList.addStrings ("dog", "cat", "bird");
}

我不明白错误消息:

Test.cpp:22:11: error: invalid explicit specialization before '>' token
 template <>
           ^
Test.cpp:22:11: error: enclosing class templates are not explicitly specialized
Test.cpp:23:39: error: template parameters not used in partial specialization:
 class StringList<StreamType, stream>::AddStrings<> {
                                       ^
Test.cpp:23:39: error:         'StreamType'
Test.cpp:23:39: error:         'stream'

这是重要的一点:

Test.cpp:22:11: error: enclosing class templates are not explicitly specialized

这意味着您无法定义作为非专用模板成员的内容的显式专用化。

class StringList<StreamType, stream>::AddStrings<> {

在这里,AddStrings是明确的专业化的,但StringList不是。这是不允许的。

尽管 Jonhathan Wakely 的建议有效,但对于那些强烈喜欢将此类嵌套化的人,因为它根本不在其他任何地方使用,我认为我们可以插入一个虚拟模板参数来AddStrings。 现在我把它保留为一个内部类,因为我非常喜欢,现在编译以下内容:

#include <iostream>
template <typename StreamType = std::ostream, StreamType& stream = std::cout>
class StringList {
    template <typename, typename...> struct AddStrings;  // The first type is a dummy type.
  public:
    template <typename... Args> void addStrings (Args&&... args) {AddStrings<void, Args...>()(args...);}
};
template <typename StreamType, StreamType& stream>
template <typename T, typename First, typename... Rest>
class StringList<StreamType, stream>::AddStrings<T, First, Rest...> : AddStrings<T, Rest...> {
  public:
    void operator()(First&& first, Rest&&... rest) {
        // do whatever
        std::cout << first << ' ';
        AddStrings<T, Rest...>::operator()(std::forward<Rest>(rest)...);
    }
};
template <typename StreamType, StreamType& stream>
template <typename Dummy>
class StringList<StreamType, stream>::AddStrings<Dummy> {
  public:
    void operator()() const {}  // End of recursion.
};
int main() {
    StringList<> stringList;
    stringList.addStrings ("dog", "cat", "bird");
}