9

我正在考虑关于 const 和非常量类方法的这个问题。首选答案来自 Scott Meyers 的 Effective C++,其中非常量方法是根据 const 方法实现的。

进一步扩展,如果方法返回迭代器而不是引用,如何减少代码重复?修改链接问题中的示例:

class X
{
    std::vector<Z> vecZ;    
public:
    std::vector<Z>::iterator Z(size_t index)
    {
        // ...
    }
    std::vector<Z>::const_iterator Z(size_t index) const
    {
        // ...
    }
};

我无法根据 const 方法实现非常量方法,因为不使用 distance()/advance() 技术就无法直接从 const_iterator 转换为迭代器。

在示例中,因为我们使用 std::vector 作为容器,实际上可以从 const_iterator 转换为迭代器,因为它们很可能被实现为指针。我不想依赖这个。有没有更通用的解决方案?

4

3 回答 3

5

您可以使用一些技巧。如果您对容器具有非常量访问权限,则可以将 const_iterator 转换为迭代器。(你做的):

std::vector<Z>::iterator Z(size_t index)
{
    std::vector<Z>::const_iterator i = static_cast<const X&>(*this).Z(index);
    return vecZ.erase(i, i);
}

你也可以这样做:

std::vector<Z>::iterator Z(size_t index)
{
    return std::next(vecZ.begin(), std::distance(vecZ.cbegin(), static_cast<const X&>(*this).Z(index)));
}

两者都不是特别优雅。为什么我们没有点const_iterator_castconst_pointer_cast?也许我们应该。

编辑,我错过了最明显和最优雅的解决方案,因为我试图使用非常量方法中的 const 方法。在这里我做相反的事情:

std::vector<Z>::const_iterator Z(size_t index) const
{
    return const_cast<X&>(*this).Z(index);
}

您正在取消引用结果,const_cast但是只要非常量Z不修改X. 与我提供的其他两种解决方案不同,这是我可能在实践中使用的一种。

于 2013-01-21T19:50:02.983 回答
2

我相信,只有借助助手才有可能

typedef int Z;

class X
{
    std::vector<Z> vecZ;    
public:
    std::vector<Z>::iterator foo(size_t index)
    {
        return helper(*this);
    }
    std::vector<Z>::const_iterator foo(size_t index) const
    {
        return helper(*this);
    }

    template <typename T>
    static auto helper(T& t) -> decltype(t.vecZ.begin())
    {
        return t.vecZ.begin();
    }
};

编辑 同样可以在没有 c++11 的情况下实现

template <typename T>
struct select
{
    typedef std::vector<Z>::iterator type;
};
template <typename T>
struct select<const T&>
{
    typedef std::vector<Z>::const_iterator type;
};

template <typename T>
static
typename select<T>::type
helper(T t) 
{
    return t.vecZ.begin();
}

但是,好吧,我认为您在使用此方法之前应该三思而后行

于 2013-01-21T19:59:28.287 回答
1

如果您使用的是 C++11,则有一种更优雅(恕我直言)的方式,它在模板迭代器类中仅使用两个 typedef 来区分 const 和常规迭代器: http ://www.sjvs.nl/c-实现-const_iterator-and-non-const-iterator-without-code-duplication/

于 2013-07-03T13:56:55.597 回答