Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/154.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何将常量指针向量转换为非常量指针向量?_C++_Pointers_Vector_Const Cast - Fatal编程技术网

C++ 如何将常量指针向量转换为非常量指针向量?

C++ 如何将常量指针向量转换为非常量指针向量?,c++,pointers,vector,const-cast,C++,Pointers,Vector,Const Cast,我有一个函数,它在自定义列表实现中查找元素。为了使它保持正确,我可以完成这个整洁的重载,甚至可以使用一行程序来重用相同的实现,因此不必重复逻辑 const MyObject* findObject(const MyList& list) { //... } MyObject* findObject(MyList& list) { return const_cast<MyObject*>(findObject(const_cast<const MyLis

我有一个函数,它在自定义列表实现中查找元素。为了使它保持正确,我可以完成这个整洁的重载,甚至可以使用一行程序来重用相同的实现,因此不必重复逻辑

const MyObject* findObject(const MyList& list)
{
  //...
}

MyObject* findObject(MyList& list)
{
  return const_cast<MyObject*>(findObject(const_cast<const MyList&>(list)));
}
constmyobject*findObject(constmylist&list)
{
//...
}
MyObject*findObject(MyList和list)
{
返回const_cast(findObject(const_cast(list));
}
问题是,一旦我需要在向量中返回多个元素指针,我该怎么做,以阻止像reinterpret_cast这样的未保存/不可移植的黑客行为

std::vector<const MyObject*> findObject(const MyList& list)
{
  //...
}

std::vector<MyObject*> findObject(MyList& list)
{
  // this is sth I'm looking for:
  const_element_cast<std::vector<MyObject*>>( findObject( const_cast<const MyList&>(list)) );
}
std::vector findObject(const MyList&list)
{
//...
}
std::vector findObject(MyList和list)
{
//这是我正在寻找的东西:
常量元素转换(findObject(常量转换(列表));
}

最简单的解决方案是忘记
const\u cast
,直接实现这两个重载这是标准库实现的功能。

例如,
std::vector
具有
const
操作符[]
的非
const
版本。VC++和GCC都有该操作符的重复实现(分别参见
include/vector
stl_vector.h
文件);他们都不会使用任何
const_cast
技巧来复制这种行为

现在,如果您的
findObject
实现非常大和复杂,那么第一个选择应该是简化它。作为一个临时解决方案,您可以考虑在内部(私有或其他不可访问)模板函数的基础上实现重载,使用<代码> DeCytys/COD>尾随返回类型来获得正确的<代码> const < />代码>或非->代码> const < /Cord>返回类型。下面是一个简单的例子:

#include <iostream>
#include <vector>
#include <typeinfo> // just to demonstrate what's going on

// simple example data structure:
struct MyObject {};
struct MyList
{
    MyObject elements[3] = { MyObject {}, MyObject {}, MyObject {} };
};

namespace internal
{
    // &list.elements[0] will be either MyObject const* or MyObject*
    template <class ConstOrNonConstList>
    auto doFindObject(ConstOrNonConstList& list) -> std::vector<decltype(&list.elements[0])>
    {
        // let's say there was an immensely complicated function here,
        // with a lot of error potential and maintenance nightmares
        // lurking behind a simple copy & paste solution...

        // just to demonstrate what's going:
        std::cout << typeid(decltype(&list.elements[0])).name() << "\n";

        std::vector<decltype(&list.elements[0])> result;
        for (auto&& element : list.elements)
        {
            result.push_back(&element);
        }
        return result;
    }
}

std::vector<const MyObject*> findObject(const MyList& list)
{
    std::cout << "const version\n";
    return internal::doFindObject(list);
}

std::vector<MyObject*> findObject(MyList& list)
{
    std::cout << "non-const version\n";
    return internal::doFindObject(list);
}

int main()
{
    MyList list1;
    MyList const list2;
    auto obj1 = findObject(list1);
    auto obj2 = findObject(list2);
}

但坦率地说,我不会这么做。它似乎设计过度,而且可能有点太聪明了。过于聪明的代码很少是个好主意,因为它会让人困惑。

选项1

如果您愿意支付循环+复制价格(相对于复制粘贴代码):

std::vector c_vec=static_cast(this)->my_const_func();
std::载体ret;
for(const thing*t:c_vec){
//是的,你可以这样做,因为这个函数不是常量
//因此,保证您处于非常量上下文中。
//见斯科特·迈尔斯。
后推回(连续铸造(t));
}
返回ret;
选项2

[编辑]如果您不想支付循环+复制价格,这里有另一种选择

假设您使用的是cpp文件(不仅仅是头文件)。在编译单元(.cpp)中,添加一个模板化的getter

template <class T, class MyObj>
std::vector<T*> getter_imp(MyObj& obj, int someval) {
    assert(someval <= 42);

    std::vector<T*> ret;
    for (auto& i : obj._my_vec) {
        if (i < someval) {
            ret.push_back(&i);
        }
    }
    return ret;
}
模板
向量getter_imp(MyObj&obj,int-someval){

assert(someval)
const_cast(list)
参数上的
const
说明符是对调用方的一种保证,即函数不会更改传递给它的数据。这不是要传递的数据的要求。您可以传递非const数据。因此您的
const_cast(list)
是无意义的。另外,从
findObject()返回
const MyObject*
也是毫无意义的。为了理解为什么,请考虑这个代码:<代码> const int c=42;int i= c;< /c> >正确地写下它并悄悄地远离这些幼稚的const铸造思想。你知道为什么他们会在枪上安上安全的抓取器,对吗?@舍尔吉避免了无限递归?@ Rok错了。这是借用Scott Meyer的有效C++的技术。F库设计者避免了它的缺点是什么?到目前为止,我真的看不到任何东西。即使是太大,也总是不可能重整整个方法。例如,考虑处理已测试的遗留代码。尽管如此,即使它最终只限于边界检查和其他基础知识,我还是希望它一次性完成并使用。两次,而不是在两个位置复制,如果开发人员进行更改,则依赖开发人员同步这两个位置(实际经验表明:他通常不会)
std::vector<const thing*> c_vec = static_cast<const me*>(this)->my_const_func();
std::vector<thing*> ret;

for (const thing* t : c_vec) {
    // Yes you can do this, since this func isn't const
    // so you are guaranteed to be inside non-const context.
    // See Scott Meyers.

    ret.push_back(const_cast<thing*>(t));
}
return ret;
template <class T, class MyObj>
std::vector<T*> getter_imp(MyObj& obj, int someval) {
    assert(someval <= 42);

    std::vector<T*> ret;
    for (auto& i : obj._my_vec) {
        if (i < someval) {
            ret.push_back(&i);
        }
    }
    return ret;
}
template <class T, class MyObj>
friend std::vector<T*> getter_imp(MyObj&, int);
std::vector<const int*> get(int v) const {
    return getter_imp<const int>(*this, v);
}
std::vector<int*> get(int v) {
    return getter_imp<int>(*this, v);
}