Extending the parameter package in parentheses gives a strange result

I am trying to implement a function that takes a variable number of lines and forwards to a print function that expects a pointer charand sizefor each line alternating.

Example:

std::string a = "123";
std::string b = "1234";
forward(a, b); // should call doPrint(a.c_str(), a.size(), b.c_str(), b.size())

I thought the following should be the correct implementation, but despite the fact that it compiles, the behavior is very surprising to me.

template <class ...Args>
void forward(const Args & ... args) {
  doPrint( (args.c_str(), args.size())...);
}

forward(a, b)causes doPrint(3, 4), not doPrint("123", 3, "1234", 4)as if I wrote doPrint((args.size())...). The call is c_str()completely ignored by the compiler.

I tried g++, clangand iccwith all the conclusions of the same output. What is wrong with (args.c_str(), args.size())...?

, std::make_tuple(args.c_str(), args.size())... , , , , doPrint, .

+4
4

, .
:

    int a = (1, 2, 3, 4, 5, 6);
    assert(a == 6);

:

    doPrint(std::tuple_cat(std::make_tuple(argc.c_str(), args.size())...));

doPrint ; .

:

    template <class Tuple, std::size_t ... indices>
    doPrint(Tuple t, std::integer_sequence<size_t, indices...>)
    {
        doPrint(std::get<indices>(t)...);
    }

    template <class Tuple>
    doPrint(Tuple t)
    {
        doPrint(t, std::make_index_sequence<std::tuple_size<Tuple>::value>());
    }

, , , , .

+7

(args.c_str(), args.size()) - , , , (args.size()).

, doPrint !

doPrint, , .

+5

, :

#include <string>
#include <utility>
#include <tuple>

extern void doPrint(...);

namespace detail {
  template<std::size_t...Is, class Tuple>
  void forward(std::index_sequence<Is...>, Tuple&& tuple)
  {
    doPrint(std::get<Is>(tuple)...);
  }
}

template<class...Strings>
void forward(Strings&&... strings)
{
  detail::forward(std::make_index_sequence<sizeof...(Strings) * 2>(),
          std::tuple_cat(std::make_tuple(strings.data(), strings.size())...)
          );
}

int main()
{
  std::string a = "123";
  std::string b = "1234";
  forward(a, b); // should call doPrint(a.c_str(), a.size(), b.c_str(), b.size())
}
+3

:

http://articles.emptycrate.com/2016/05/09/variadic_expansion_wrap_up.html

template< typename ... T >
void do_print(T ... args)
{
    (void)std::initializer_list<int> {
        (std::cout << args.c_str() << ": "
        << args.size() << "\n",     0)...
    };
}

template< typename ... T >
void forward_print(T ... args)
{
    do_print(args...);
}
int main(int argc, const char * argv[])
{
    std::cout << "Hello, World!\n";

    std::string a = "1234";
    std::string b = "567";

    forward_print(a, b);

    return 0;
}

This works with g ++ -std = C ++ 11

+1
source

All Articles