测试传递给函数的void*是否是shared_ptr或unique_ptr

Testing if a void* passed into a function is either a shared_ptr or a unique_ptr

本文关键字:ptr 是否是 shared unique void 函数 测试      更新时间:2023-10-16

我正在为类创建一个函数,参数被声明为void*,但在函数中,我需要测试这个void*是否为shared_ptr或unique_ptr是否有方法测试这种类型的情况?

这是我到目前为止正在研究的;我的类是模板类型,不存储任何成员变量。它有一个默认构造函数,它也可以通过传递shared_ptr<Type>unique_ptr<Type>来构造,它有多个allocate()函数,它们做相同类型的工作。

#ifndef ALLOCATOR_H
#define ALLOCATOR_H
#include <memory>
#include <iostream>
template<class Type>
class Allocator {
public:
    Allocator(){}
    Allocator( Type type, void* pPtr );
    Allocator( std::shared_ptr<Type>& pType );
    Allocator( std::unique_ptr<Type>& pType );
    // ~Allocator(); // Default Okay
    void allocate( std::shared_ptr<Type>& pType );
    void allocate( std::unique_ptr<Type>& pType );
    void allocate( Type type, void* pPtr );
private:
    Allocator( const Allocator& c ); // Not Implemented
    Allocator& operator=( const Allocator& c ); // Not Implemented
}; // Allocator
#include "Allocator.inl"
#endif // ALLOCATOR_H

我的*.cpp文件只有#include "Allocator.h",因为所有的实现都在我的*.inl文件。

两个构造函数:Allocator( std::shared_ptr<Type>& pType ); &Allocator( std::unique_ptr<Type>& pType );以及两个匹配的allocate()函数工作良好。构造函数Allocator( Type type, void* pPtr );及其匹配函数是我遇到麻烦的地方。

构造函数本身是直接的,因为它所做的只是调用匹配的函数,将变量传递给它。

template<class Type>
Allocator<Type>::Allocator( Type type, void* pPtr ) {
    allocate( type, eType, pPtr );
}

这是在功能实现,我是挣扎。

template<class Type>
void Allocator<Type>::allocate( Type type, void* pData ) {
    if ( pData == reinterpret_cast<void*>( std::shared_ptr<Type ) ) {
        std::shared_ptr<Type> pShared;
        pShared.reset( new Type( type ) );
        pData = reinterpret_cast<void*>( pShared );
    } else if ( pData == reinterpret_cast<void*>( std::unique_ptr<Type ) ) {
        std::unique_ptr<Type> pUnique;
        pUnique.reset( new Type( type ) );
        pData = reinterpret_cast<void*>( pUnique );
    } else {
        std::cout << "Error invalid pointer type passed in << std::endl
                  << "must be either a std::shared_ptr<Type> << std::endl
                  << "or a std::unique_ptr<Type> << std::endl;
    }            
}

除了检查是否传入void*std::shared_ptr<Type>std::unique_ptr<Type>的其他问题,我可能会有,是我使用reinterpret_cast<void*>的正确方式将智能指针转换为void指针,如果不是如何实现?

你不能检查void*是什么类型。这是void*。就是这样。它不像boost::any,它狡猾地隐藏了一些其他类型信息。就是 void*。你不能检查它是什么类型的。你无法测试它是否来自一个特定的类型。你没有任何信息。邮政编码。没有什么结果。无价值之物。空白。

void*指针不携带任何类型信息。您需要做的是与void*一起传递一个附加值,以指定void*指向的内容,然后您可以相应地对其进行类型转换。

#ifndef ALLOCATOR_H
#define ALLOCATOR_H
#include <memory>
#include <iostream>
template<class Type>
class Allocator {
public:
    enum AllocateType { eSharedPtr, eUniquePtr };
    Allocator() {}
    Allocator( Type type, std::shared_ptr<Type>& pData );
    Allocator( Type type, std::unique_ptr<Type>& pData );
    // ~Allocator(); // Default Okay
    void allocate( Type type, std::shared_ptr<Type>& pData );
    void allocate( Type type, std::unique_ptr<Type>& pData );
private:
    Allocator( const Allocator& c ); // Not Implemented
    Allocator& operator=( const Allocator& c ); // Not Implemented
    void allocate( Type type, AllocateType eDataType, void* pData );
}; // Allocator
#include "Allocator.inl"
#endif // ALLOCATOR_H

template<class Type>
Allocator<Type>::Allocator( Type type, std::shared_ptr<Type>& pData ) {
    allocate( type, pData );
}
template<class Type>
Allocator<Type>::Allocator( Type type, std::unique_ptr<Type>& pData ) {
    allocate( type, pData );
}
template<class Type>
void Allocator<Type>::allocate( Type type, std::shared_ptr<Type>& pData ) {
    allocate( type, eSharedPtr, &pData );
}
template<class Type>
void Allocator<Type>::allocate( Type type, std::unique_ptr<Type>& pData ) {
    allocate( type, eUniquePtr, &pData );
}
template<class Type>
void Allocator<Type>::allocate( Type type, AllocateType eDataType, void* pData ) {
    switch (eDataType) {
        case eSharedPtr: {
            static_cast<std::shared<Type>*>(pData)->reset( new Type( type ) );
            break;
        }
        case eUniquePtr: {
            static_cast<std::unique_ptr<Type>*>(pData)->reset( new Type( type ) );
            break;
        }
    }
}

在这种情况下,我甚至不会费心尝试将所有内容都汇集到一个函数中,以

开头:
#ifndef ALLOCATOR_H
#define ALLOCATOR_H
#include <memory>
#include <iostream>
template<class Type>
class Allocator {
public:
    Allocator() {}
    Allocator( Type type, std::shared_ptr<Type>& pData );
    Allocator( Type type, std::unique_ptr<Type>& pData );
    // ~Allocator(); // Default Okay
    void allocate( Type type, std::shared_ptr<Type>& pData );
    void allocate( Type type, std::unique_ptr<Type>& pData );
private:
    Allocator( const Allocator& c ); // Not Implemented
    Allocator& operator=( const Allocator& c ); // Not Implemented
}; // Allocator
#include "Allocator.inl"
#endif // ALLOCATOR_H

template<class Type>
Allocator<Type>::Allocator( Type type, std::shared_ptr<Type>& pData ) {
    allocate( type, pData );
}
template<class Type>
Allocator<Type>::Allocator( Type type, std::unique_ptr<Type>& pData ) {
    allocate( type, pData );
}
template<class Type>
void Allocator<Type>::allocate( Type type, std::shared_ptr<Type>& pData ) {
    pData.reset( new Type( type ) ) ;
}
template<class Type>
void Allocator<Type>::allocate( Type type, std::unique_ptr<Type>& pData ) {
    pData.reset( new Type( type ) );
}

经过一番考虑,并且知道这个类并不在内部存储任何成员变量,只包含执行特定任务的函数后,我采用了一种不同的方法。我非常感谢每个人的反馈和回答,因为他们确实对我最初提出的基本问题给出了很好的有效答案。这是我从你的建议中得到的。我去掉了这个类本身是模板的规定,将默认构造函数设为private。我确保每个函数都是一个函数模板,并使它们成为静态的。这是我的新类:

Allocator.h

#ifndef ALLOCATOR_H
#define ALLOCATOR_H
#include <memory>
class Allocator {
public:
    template<class Type>
    inline static void allocate( std::shared_ptr<Type>& pShared, const Type& type = Type() );
    template<class Type>
    inline static void allocate( std::unique_ptr<Type>& pUnique, const Type& type = Type() );
private:
    Allocator();
    Allocator( const Allocator& c );
    Allocator& operator=( const Allocator& c );
}; // Allocator
#include "Allocator.inl"
#endif // Allocator

Allocator.cpp

#include "Allocator.h"

Allocator.inl

template<class Type>
inline void Allocator::allocate( std::shared_ptr<Type>& pShared, const Type& type ) {
    pShared.reset( new Type( type ) );  
}
template<class Type>
inline void Allocator::allocate( std::unique_ptr<Type>& pUnique, const Type& type ) {
    pUnique.reset( new Type( type ) );
}

这使得使用该类变得简单。

main.cpp

#include <iostream>
#include <conio.h>
#include "Allocator.h"
class A {
private:
    int m_a;
public:
    explicit A( int a = 0 ) : m_a( a ) {}
    A( const A& a ) { this->m_a = a.m_a; }
    int  getA() const { return m_a; }
    void setA( int a ) { m_a = a; }
}; // A
int main() {
    // Creating Smart A Pointer Just From A Class Type
    std::shared_ptr<A> pShared;
    std::unique_ptr<A> pUnique;
    Allocator::allocate( pShared );
    Allocator::allocate( pUnique );
    std::cout << "Shared: " << pSharedA->getA() << std::endl;
    std::cout << "Unique: " << pUniqueA->getA() << std::endl;
    pSharedA->setA( 4 );
    pUniqueA->setA( 5 );
    std::cout << "Shared: " << pSharedA->getA() << std::endl;
    std::cout << "Unique: " << pUniqueA->getA() << std::endl;
    // Create A Smart Pointer From An Object Of Type In This Case A
    // This next sections does rely on the fact that Type in this case A, should have a copy constructor defined.
    A a1( 3 );
    std::shared_ptr<A> sharedA;
    std::unique_ptr<A> uniqueA;
    Allocator::allocate( sharedA, a1 );
    Allocator::allocate( uniqueA, a1 );
    std::cout << "Shared: " << sharedA->getA() << std::endl;
    std::cout << "Unique: " << uniqueA->getA() << std::endl;
    sharedA->setA( 6 );
    uniqueA->setA( 7 );
    std::cout << "Shared: " << sharedA->getA() << std::endl;
    std::cout << "Unique: " << uniqueA->getA() << std::endl;
    pSharedA.reset();
    pUniqueA.release();
    pUniqueA.reset();
    sharedA.reset();
    uniqueA.release();
    uniqueA.reset();
    std::cout << std::endl << "Press Any Key To Quit" << std::endl;
    _getch();
    return 0;
} // main

这也消除了做任何类型转换、比较等的需要,提高了所做工作的效率。我甚至可以更进一步,将所有这些函数声明为内联。

编辑

我采纳了Remy Lebeau的建议,通过添加Type type作为默认形参删除了两个重载函数,并将其更改为通过const引用传递。