この残念ながら長い例は、私が書こうとしている実際のコードの簡略版です。これには 2 つの問題があります。まず、書かれているように、コンパイルされません: エラーは
error: cannot bind ‘std::string’ lvalue to ‘std::string&&’
error: initializing argument 3 of ‘void pack_arg(datum*, size_t, std::string&&)’
への呼び出しの存在によってトリガーされshut_the_door
ます。&&
の関連するオーバーロードでを取り出すと、pack_arg
コンパイルされますが、生成されたコードは両方の文字列を不必要にコピーしているように見えます。d
2 番目に、配列がポインターを保持しているすべての文字列テンポラリが、vprocess
. 現在、生成されたコードは、その呼び出しの直前にそれらを破壊しているように見えます。
process
他のすべてのそのような引数とは関係なく、オーバーロード可能な関数呼び出しを介して各引数を実行する機会がある限り、配列がどのように埋められるかについて非常に根本的な変更を検討するつもりです。(特に、一時的に参照を初期化するための特別な規則により、共用体で使用できれば問題 2 が解消されるのではないかと思いますstd::string&
が、配列の各メンバーはdatum
初期化ではなく代入によって埋められるため、現在はそうではありませんの呼び出しを失うことなく、初期化によってそれを埋める方法がわかりませんpack_arg
。これは、より大きなコンテキストで必要です。)
編集:std::forward
betweenpack_args
との使用はpack_arg
役に立たないようです。まったく同じエラー メッセージが表示されます。
#include <string>
#include <stddef.h>
using std::string;
union datum
{
const string* s;
int i;
};
inline void
pack_arg(datum* d, size_t n, int t)
{
d[n].i = t;
}
inline void
pack_arg(datum* d, size_t n, string && t)
{
d[n].s = &t;
}
inline void
pack_args(datum*, size_t)
{
}
template <typename X, typename... XS> inline void
pack_args(datum* d, ::size_t n, X&& x, XS&&... xs)
{
pack_arg(d, n, x);
pack_args(d, n+1, xs...);
}
extern void vprocess(datum*, size_t);
template <typename... XS> inline void
process(XS&&... xs)
{
size_t n = sizeof...(xs);
datum d[n];
pack_args(d, 0, xs...);
vprocess(d, n);
}
extern string shut_the_door();
void
demo()
{
process(1, 2, "buckle my shoe", 3, 4, shut_the_door());
}