Home > Software engineering >  How create argument list in C during runtime to pass this to a template function(..., Ts &&... val
How create argument list in C during runtime to pass this to a template function(..., Ts &&... val

Time:03-05

I want to program the google-cloud-spanner in C .

The api-package I use is from https://github.com/googleapis/google-cloud-cpp.
In the code https://github.com/googleapis/google-cloud-cpp/blob/main/google/cloud/spanner/samples/samples.cc from line 1677ff, one can see the method "EmplaceRow" from "InsertOrUpdateMutationBuilder", or the not very much simpler "MakeInsertOrUpdateMutation" from line 1739 till 1743.
Looking in
https://googleapis.dev/cpp/google-cloud-spanner/latest/namespacegoogle_1_1cloud_1_1spanner.html
the example code for "EmplaceRow" and "MakeInsertOrUpdateMutation" can be seen. More precise you can see the "EmplaceRow" example code on
https://googleapis.dev/cpp/google-cloud-spanner/latest/namespacegoogle_1_1cloud_1_1spanner.html#a3451b640c4ee19df694fa0539047fcdc
and the "MakeInsertOrUpdateMutation" example code on
https://googleapis.dev/cpp/google-cloud-spanner/latest/namespacegoogle_1_1cloud_1_1spanner.html#aced68ba9bc789f44693ad29962fc6ed6

My Problem is:
How can I create a variable (!) list of arguments to pass them into "EmplaceRow" or in "MakeInsertOrUpdateMutation" as "Ts &&... values".
And the "a variable list of arguments" means that this "list" (not a std::list) can be used in the mentioned manner as "Ts &&... values"-list.

Until now I did a lot of searching for a solution but I found no propper one:

  1. Two template functions by using a std::tuple to expand its tuple elements to the "Ts &&... values"-list.
  2. Two template functions by using a std::array to expand its array elements to the "Ts &&... values"-list.

Both solutions are "nice" but not useful!
I want process different tables with different number of columns during runtime but the size of std::tuple and std::array have to be fixed at compile-time (!).
Thus, creating a "Ts &&... values"-list during runtime can't be solved by std::tuple and std::array.

So ... how can I create from a std::vector, std::list, or other container-types, which could be created, resized and filled with "spanner::Value"-values, that "Ts &&... values"-list to pass it to "EmplaceRow" or "MakeInsertOrUpdateMutation".

Here is my code for expanding the std::tuple to an "Ts &&... values"-list:

template <typename Tuple, std::size_t... I>
int myInsrtOrUpdMutBldEmplaceRowBuild_Tup(confDataProc::processConfigData testA,
                                          Tuple const& tuple,
                                          std::index_sequence<I...>)
{
  namespace spanner = ::google::cloud::spanner;

  //std::cout << "the second 'myInsrtOrUpdMutBldEmplaceRowBuild_Tup'" << std::endl;
  auto client = GoClSp::MakeSampleClient(testA.getProjectID(), 
                                         testA.getInstanceID(),
                                         testA.getDatabaseID());
  auto commit = client.Commit(spanner::Mutations{
                              spanner::InsertOrUpdateMutationBuilder(
                                        testA.getTableName(),
                                        testA.getColumnNamesOfTable())
                                        .EmplaceRow(std::get<I>(tuple)...)
                                            .Build()});
  if (!commit)
  {
    throw std::runtime_error(commit.status().message());
  }

  return 0;
}
template <typename Tuple>
int myInsrtOrUpdMutBldEmplaceRowBuild_Tup(confDataProc::processConfigData testA,
                                          Tuple const& tuple)
{
  //std::cout << "the first 'myInsrtOrUpdMutBldEmplaceRowBuild_Tup'" << std::endl;

  int iRetVal = myInsrtOrUpdMutBldEmplaceRowBuild_Tup(testA, 
                        tuple,
                        std::make_index_sequence<std::tuple_size<Tuple>::value>());

  return iRetVal;
}

This code works, but the big problem is that the size of the std::tuple must be known during compile time and can't be created during runtime with variable size/length. The size/length is in this context the number of columns of the processed table.

Maybe the solution is very obvious for other (better) programmers than me or maybe it is difficult. But anyway a helpful code snipped or a useful link is always welcome.

By the way:
In my experience this is very different to the 'classic' variadic arguments.
I have no possibility to change the behaviour of the method "EmplaceRow" or "MakeInsertOrUpdateMutation" - if I had I would like to change the "Ts &&... values"-list to a simpler "std::vectorspanner::Value values".

On the other hand:
If there is a other C function to insert or update table rows in a cloud-spanner table which I do not know, please inform me.
I "only" need a solution for insert or update a row of a table in C , I do not insist on the way described above.

CodePudding user response:

Replace EmplaceRow with AddRow and that should do the trick.

You cannot convert runtime arguments to template arguments in a practical way here. (I could less than helpfully show you how, but trust me, bad plan here; I only don't say "impossible" because I dislike lying.)

I find google's C docs to require being willing and able to read the raw headers and sometimes source code. Here, I found the class where EmplaceRow was defined and looked for either what it did, or an alternative method.

Emplace in C lingo means "perfect forward into storage"; usually there is an imperfect forwarding method nearby (like, push_back vs emplace_back) for when templates get in the way.

  • Related