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

时间:2015-10-07 22:30:09

标签: c++ smart-pointers void-pointers reinterpret-cast

我正在为类创建一个函数,并且参数被声明为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 );&amp; 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*>我可能会遇到的其他问题之外,我使用的是unittest将智能指针转换为void指针的正确方法,如果没有,怎么能实现呢?

3 个答案:

答案 0 :(得分:8)

您无法检查dismissViewControllerAnimated:completion:的类型。它是void*。就是这样。它不像void*那样狡猾地隐藏了其他类型的信息。它的只是 boost::any。你无法检查它来自哪种类型。您无法测试它是否来自特定类型。你没有信息。压缩。纳达。小人物。虚空。

答案 1 :(得分:1)

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 ) );
}

答案 2 :(得分:0)

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

<强> 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引用传递。我还将函数内联。