所以我有一个结构 X:
struct X
{
int typecode;
char* pData;
int length;
...
}
和一长串类型,我们称这个集合为 TS。TS 包括大多数原始类型和几种类类型。
对于 TS 中的每种类型 T,我定义了一个常规函数:
void setup(X& x, const T& t);
例如对于 T = 字符串设置如下所示:
void setup(X& x, const string& s)
{
x.typecode = X_STRING;
x.pData = s.c_str();
x.length = s.size();
...
}
现在我有一个模板函数 convert_to_x:
template<class T>
X convert_to_x(const T& t)
{
X x;
memset(x, 0, sizeof(x));
setup(x, t);
return x;
}
还有一个函数 f,它接受一个 X 数组:
void f(X* xs, int num_args);
还有一个可变参数模板函数g
:
template<class... Args)
void g(Args... args)
{
constexpr num_args = sizeof...(args);
X xs[] = { convert_to_x(args)... };
f(xs, num_args);
}
发生的事情是,您可以使用任意数量的参数和类型调用 g,它将参数转换为 X 类型的数组,然后调用 f。
问题是,如果 g 被调用的类型不在 TS 中,但可以转换为 TS 中的类型,则会发生以下情况:
- 调用转换构造函数来创建临时 t。
setup
将存储一个指向这个临时的指针。- 临时的被破坏了。
- f 使用包含悬挂指针的 xs 调用。
我需要一种方法g
来转换任何可转换为 TS 中的类型但不是 TS 中的类型的参数,并将它们保留在g
.
实现这一目标的最佳方法是什么?
更新:
我刚刚想到的一种可能可行的方法是为convert
TS 中的每种类型 T 定义一个常规函数,如下所示:
T convert(const T& t) { return t; }
然后为 g 定义一个包装器:
template<class... Args>
void g2(Args... args)
{
g(convert(args)...);
}
但我认为这会导致不必要地复制已经在 TS 中且不需要转换的类型。有没有办法使用右值/左值语义来避免这种情况?
更新 2:
也许这会起作用:
对于 TS 中的每个 T:
const T& convert(const T& t) { return t; }
T convert(const T&& t) { return t; }
然后:
template<class... Args>
void g2(Args... args)
{
g(convert(args)...);
}
是否有任何情况下安装程序可能会收到上述临时文件?