模板中返回std::set<T>::iterator错误

5

我正在创建一个围绕std::set的模板包装器。为什么我在Begin()函数声明中得到错误?

template <class T>
class CSafeSet
{
    public:
        CSafeSet();
        ~CSafeSet();

        std::set<T>::iterator Begin();

    private:
        std::set<T> _Set;
};

错误:类型‘std :: set,std :: allocator<_CharT> >’不是从类型‘CSafeSet’派生的


3
顺便说一句:请阅读有关在标识符中使用下划线的内容。https://dev59.com/KHVC5IYBdhLWcg3woSxW#228797 - Martin York
1
简短版:不要以下划线开头命名标识符。 - jalf
下划线后跟大写字母的是编译器保留的。双下划线后跟任何内容也是编译器保留的。 - GManNickG
1个回答

17

试试使用 typename 工具:

template <class T>
class CSafeSet
{
    public:
        CSafeSet();
        ~CSafeSet();

        typename std::set<T>::iterator Begin();

    private:
        std::set<T> _Set;
};

你需要在那里使用typename,因为它依赖于模板T。在代码上面的链接中有更多信息。如果使用typedef,许多这些东西会变得更容易:

template <class T>
class CSafeSet
{
    public:
        typedef T value_type;
        typedef std::set<value_type> container_type;
        typedef typename container_type::iterator iterator_type;
        typedef typename container_type::const_iterator const_iterator_type;

        CSafeSet();
        ~CSafeSet();

        iterator_type Begin();

    private:
        container_type _Set;
};

顺便提一句,如果你想做到完整性,你需要允许CSafeSet像 set一样完成同样的事情,这意味着要使用自定义的比较器和分配器:

template <class T, class Compare = std::less<T>, class Allocator = std::allocator<T> >
class CSafeSet
{
    public:
        typedef T value_type;
        typedef Compare compare_type;
        typedef Allocator allocator_type;

        typedef std::set<value_type, compare_type, allocator_type> container_type;
        typedef typename container_type::iterator iterator_type;
        typedef typename container_type::const_iterator const_iterator_type;

        // ...
}

最后一条建议,如果你要创建一个类的包装器,请尽量遵循与该类相同的命名约定。也就是说,你的 Begin() 应该改为 begin()(个人认为在类名前加 C 有点奇怪,但这取决于你 :]


1
请注意,您的CSafeSet类模板存在错误。您还需要使用typename定义迭代器类型,因为它们也是相关的。例如:typedef typename container_type::iterator iterator_type; 没有这个typename,它在符合标准的编译器中不应该被编译。我猜您可能尝试在Visual Studio中运行它(在2008年之前的版本中,当时这个问题已经得到解决),这些版本错误地接受了这样的代码而没有typename。 - Leandro T. C. Melo
我根本没有尝试过,谢谢你指出来,我很傻(这很常见) :) - GManNickG
顺便提一句,我认为使用大写名称将强调这不是原始的STL类。我不确定我是否会在我的CSafeSet中实现所有 std::set方法。 - jackhab

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接