簡體   English   中英

如何將智能指針的向量轉換為常量向量,該向量包含指向常量的智能指針?

[英]How do you cast a vector of smart pointers to a constant vector that hold smart pointers that point to constants?

我有一個叫做Thing的課程。 我創建了一個shared_ptr<Thing>>的向量。 現在我想將其傳遞給函數或類似的東西: const vector<shared_ptr<const Thing>>

下面的代碼可以編譯,但是我更願意避免使用reinterpret_cast來確保類型安全,因為我不知道這可能如何影響智能指針的行為。

#include <memory>
#include <vector>

using namespace std;

class Thing {};

typedef vector<shared_ptr<Thing>>             VectorOfThings;
typedef const vector<shared_ptr<const Thing>> VectorOfConstThings;

int main() {
    VectorOfThings *things;
    auto           constThings = reinterpret_cast<VectorOfConstThings *> (things);
}

這與智能指針無關。 C ++標准不允許在container <T>和container <T const>之間進行轉換。 之前已經討論過: 為什么指針向量不能轉換為const指針的const向量?

將conainter <T>強制轉換為container <const T>可能是未定義的行為。

我寫了一個宏來處理類型轉換。 希望這將消除編寫所有模板代碼所產生的錯誤。

TypeHelper.h

#ifndef TYPE_HELPER_H
#define TYPE_HELPER_H

#include <memory>

/**
 * Creates a struct that has two typedefs and has several functions for reinterpret casting the regular type as
 * the constant type
 * @param NAME The name of the generated struct
 * @param REGULAR_TYPE The typedef of the non-constant type
 * @param CONSTANT_TYPE The typedef of the constant type
 * @param ... The template parameters used in REGULAR_TYPE and CONSTANT_TYPE.
 * There must be at least one parameter passed in. Even if the typedefs don't actually use them.
 * TODO If the typedefs don't need a template parameter, the user should not have to supply a dummy one.
 * TODO Implement some kind of checking to make sure that constness is the only difference.
 * TODO what happens if the template is specialized for a const of that type?
 */
#define TYPE_HELPER( NAME, REGULAR_TYPE, CONSTANT_TYPE, ... ) \
template< __VA_ARGS__ > \
struct NAME { \
typedef REGULAR_TYPE regular; \
typedef CONSTANT_TYPE constant; \
static inline constant *cast( regular *pointer ) { return reinterpret_cast<constant *> (pointer); } \
static inline constant &cast( regular &reference ) { return *reinterpret_cast<constant *> (&reference); }  \
static inline std::unique_ptr<constant> cast( std::unique_ptr<regular> unique_ptr ) { \
    return std::move( *( reinterpret_cast<std::unique_ptr<constant> *> (&unique_ptr))); \
} \
static inline std::shared_ptr<constant> cast( std::shared_ptr<regular> shared_ptr ) { \
    return std::move( *( reinterpret_cast<std::shared_ptr<constant> *> (&shared_ptr))); \
} \
};


#endif //TYPE_HELPER_H

在此文件中,我使用宏在stl矢量類周圍定義了一個包裝器

#ifndef VECTOR_TYPE_H
#define VECTOR_TYPE_H

#include <vector>
#include "TypeHelper.h"

TYPE_HELPER( VectorType,
             std::vector<std::shared_ptr<T>>,
             const std::vector<std::shared_ptr<const T>>,
             typename T );

#endif //VECTOR_TYPE_H

最后,在這里我使用類型

#include "VectorType.h"

//This is a vector of std::shared_ptr<std::string>
VectorType<std::string>::regular strings;

//This is a const vector of std::shared_ptr<const str::string>
//note that I needed to use the cast function to assign the regular one to the constant one
VectorType<std::string>::constant constStrings = VectorType<std::string>::cast(strings);

// You don't have to actually type it twice. Use auto.
auto autoConstStrings = VectorType<std::string>::cast(strings);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM