测试传入函数的 void* 是 shared_ptr 还是 unique_ptr
Testing if a void* passed into a function is either a shared_ptr or a unique_ptr
我正在为 class 创建一个函数,参数被声明为 void* 但是在函数中我需要测试这个 void* 是 shared_ptr 还是 unique_ptr 有没有办法测试这种情况?
这是我目前正在使用的;我的 class 是模板类型,不存储任何成员变量。它有一个默认的构造函数,它也可以通过传入 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*
。您无法检查它来自什么类型。您无法测试它是否来自特定类型。你的信息为零。压缩。纳达。 Zilch。空白。
一个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 ) );
}
经过一番考虑,我知道这个 class 不会在内部存储任何成员变量,只包含执行特定任务的函数,我采用了不同的方法。我非常感谢每个人的反馈和回答,因为他们确实对我最初提出的基本问题给出了很好的有效答案。这就是我从你的建议中得到的结果。我删除了这个 class 本身是模板的规定,我将默认构造函数设为私有。我确保每个函数都是一个函数模板并将它们设为静态。这是我的新 class:
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 ) );
}
这使得 class 的使用变得简单。
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 引用传递。我还内联了函数。
我正在为 class 创建一个函数,参数被声明为 void* 但是在函数中我需要测试这个 void* 是 shared_ptr 还是 unique_ptr 有没有办法测试这种情况?
这是我目前正在使用的;我的 class 是模板类型,不存储任何成员变量。它有一个默认的构造函数,它也可以通过传入 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*
。您无法检查它来自什么类型。您无法测试它是否来自特定类型。你的信息为零。压缩。纳达。 Zilch。空白。
一个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 ) );
}
经过一番考虑,我知道这个 class 不会在内部存储任何成员变量,只包含执行特定任务的函数,我采用了不同的方法。我非常感谢每个人的反馈和回答,因为他们确实对我最初提出的基本问题给出了很好的有效答案。这就是我从你的建议中得到的结果。我删除了这个 class 本身是模板的规定,我将默认构造函数设为私有。我确保每个函数都是一个函数模板并将它们设为静态。这是我的新 class:
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 ) );
}
这使得 class 的使用变得简单。
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 引用传递。我还内联了函数。