C++11:将 std::tuple 类型转换为 void* 并返回
C++11 : Cast std::tuple type to void* and back
总而言之,我想知道如何将 std::tuple 类型正确存储为 void* 并稍后将其转换回匹配的 std::tuple 类型。
问题,我的程序当前正在尝试从 void* 转换回匹配的 std::tuple 类型时崩溃,如 B::fcn 中所示。
我相信下面的代码抓住了我想做的事情的本质。一些上下文,我需要使用可怕的 void* 的原因是因为我有一个数据交换层,模型可以在其中将数据推送和拉取到另一个模型,因为它们具有指向目标模型的指针。数据交换层不支持 std::tuple 类型,但确实提供了通过推拉 void* 来支持任何类型的努力。如果由我决定,我会将数据交换层转换为模板,以便它可以直接支持任何类型的 std::tuple 但这不是一个选项。
#include <iostream>
#include <string>
#include <vector>
#include <tuple>
/* Variadic method for streaming std::vector type to cout */
template<typename T>
std::ostream& operator<<(std::ostream& stream, std::vector<T> r)
{
//Save repetitive calls to check .size()
int container_size = r.size();
//Pre-allocate loop iterator
int indx = 0;
//Check if the input vector is empty
if( container_size > 0 )
{
//Stream character for the start of a container
stream << "{ ";
//For each element of the input container, could be a value or nested container
for(indx; indx < container_size; indx++)
{
//Execute based on iterator position within container
if( indx < ( container_size - 1 ) )
{
//Print value, or recurse nested container to << template
stream << r[ indx ] << ", ";
}
else
{
//Stream last value and terminate with character
stream << r[ indx ] << " }";
}
}
}
//Default & final execution
return stream;
};
/* Start: Recursive variadic methods for streaming std::tuple type to cout */
template <size_t n, typename... T>
typename std::enable_if<(n >= sizeof...(T))>::type
print_tuple(std::ostream&, const std::tuple<T...>&)
{}
template <size_t n, typename... T>
typename std::enable_if<(n < sizeof...(T))>::type
print_tuple(std::ostream& os, const std::tuple<T...>& tup)
{
if (n != 0)
os << ", ";
os << std::get<n>(tup);
print_tuple<n+1>(os, tup);
}
template <typename... T>
std::ostream& operator<<(std::ostream& os, const std::tuple<T...>& tup)
{
os << "[";
print_tuple<0>(os, tup);
return os << "]";
}
/* End: Recursive variadic methods for streaming std::tuple type to cout */
/* An tuple alias for brevity */
using MyType = std::tuple< int, std::vector<std::string> >;
/* Dummy class for making an std::tuple and returning it as a void* */
class A
{
public:
void* fcn()
{
void *val;
int p1 = 123;
std::vector<std::string> p2 = { "Hello", "World" };
MyType p3 = std::make_tuple( p1, p2 );
val = &p3;
return val;
}
};
/* Dummy class for: receiving a void* and converting it to the expected type aliased as MyType; streaming private data member to cout */
class B
{
public:
void fcn(void *x)
{
p1 = *static_cast< MyType* >(x);
}
void print()
{
std::cout<<"\nP1 = "<<p1<<"\n";
}
private:
MyType p1;
};
/* Main program */
int main()
{
//Make instance of class A
A a;
//Make instance of class B
B b;
//Test: std::tuple -> void* -> std::tuple
b.fcn( a.fcn() );
//Test: print private data member of B
b.print();
//Exit main program
return 0;
}
fcn()
正在返回指向局部变量的悬空指针。 void*
可以用来指向任何类型的对象,但是它不包含它所指向的对象的内存。要进行类型擦除,您需要一个存储或堆分配的内存来存储对象,然后用 void* 指向它并稍后将其强制转换回来,以及管理它所指向的内存。您可以查看 std::any 来管理任何类型的对象(基本上就是这样做的)。
总而言之,我想知道如何将 std::tuple 类型正确存储为 void* 并稍后将其转换回匹配的 std::tuple 类型。
问题,我的程序当前正在尝试从 void* 转换回匹配的 std::tuple 类型时崩溃,如 B::fcn 中所示。
我相信下面的代码抓住了我想做的事情的本质。一些上下文,我需要使用可怕的 void* 的原因是因为我有一个数据交换层,模型可以在其中将数据推送和拉取到另一个模型,因为它们具有指向目标模型的指针。数据交换层不支持 std::tuple 类型,但确实提供了通过推拉 void* 来支持任何类型的努力。如果由我决定,我会将数据交换层转换为模板,以便它可以直接支持任何类型的 std::tuple 但这不是一个选项。
#include <iostream>
#include <string>
#include <vector>
#include <tuple>
/* Variadic method for streaming std::vector type to cout */
template<typename T>
std::ostream& operator<<(std::ostream& stream, std::vector<T> r)
{
//Save repetitive calls to check .size()
int container_size = r.size();
//Pre-allocate loop iterator
int indx = 0;
//Check if the input vector is empty
if( container_size > 0 )
{
//Stream character for the start of a container
stream << "{ ";
//For each element of the input container, could be a value or nested container
for(indx; indx < container_size; indx++)
{
//Execute based on iterator position within container
if( indx < ( container_size - 1 ) )
{
//Print value, or recurse nested container to << template
stream << r[ indx ] << ", ";
}
else
{
//Stream last value and terminate with character
stream << r[ indx ] << " }";
}
}
}
//Default & final execution
return stream;
};
/* Start: Recursive variadic methods for streaming std::tuple type to cout */
template <size_t n, typename... T>
typename std::enable_if<(n >= sizeof...(T))>::type
print_tuple(std::ostream&, const std::tuple<T...>&)
{}
template <size_t n, typename... T>
typename std::enable_if<(n < sizeof...(T))>::type
print_tuple(std::ostream& os, const std::tuple<T...>& tup)
{
if (n != 0)
os << ", ";
os << std::get<n>(tup);
print_tuple<n+1>(os, tup);
}
template <typename... T>
std::ostream& operator<<(std::ostream& os, const std::tuple<T...>& tup)
{
os << "[";
print_tuple<0>(os, tup);
return os << "]";
}
/* End: Recursive variadic methods for streaming std::tuple type to cout */
/* An tuple alias for brevity */
using MyType = std::tuple< int, std::vector<std::string> >;
/* Dummy class for making an std::tuple and returning it as a void* */
class A
{
public:
void* fcn()
{
void *val;
int p1 = 123;
std::vector<std::string> p2 = { "Hello", "World" };
MyType p3 = std::make_tuple( p1, p2 );
val = &p3;
return val;
}
};
/* Dummy class for: receiving a void* and converting it to the expected type aliased as MyType; streaming private data member to cout */
class B
{
public:
void fcn(void *x)
{
p1 = *static_cast< MyType* >(x);
}
void print()
{
std::cout<<"\nP1 = "<<p1<<"\n";
}
private:
MyType p1;
};
/* Main program */
int main()
{
//Make instance of class A
A a;
//Make instance of class B
B b;
//Test: std::tuple -> void* -> std::tuple
b.fcn( a.fcn() );
//Test: print private data member of B
b.print();
//Exit main program
return 0;
}
fcn()
正在返回指向局部变量的悬空指针。 void*
可以用来指向任何类型的对象,但是它不包含它所指向的对象的内存。要进行类型擦除,您需要一个存储或堆分配的内存来存储对象,然后用 void* 指向它并稍后将其强制转换回来,以及管理它所指向的内存。您可以查看 std::any 来管理任何类型的对象(基本上就是这样做的)。