如何正确实现具有可变数量的std :: string_view参数的函数?

Isk*_*tvo 4 c++ variadic-functions variadic-templates c++17

期望的行为

我基本上想要的是创建一个这样的函数:

void func(std::string_view... args)
{
    (std::cout << ... << args);
}
Run Code Online (Sandbox Code Playgroud)

它应该只能用于可转换为的类std::string_view.

例:

int main()
{
    const char* tmp1 = "Hello ";
    const std::string tmp2 = "World";
    const std::string_view tmp3 = "!";

    func(tmp1, tmp2, tmp3, "\n");

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

应该打印: Hello World!


完成的行为

到目前为止,我来到这里:

template<typename... types>
using are_strings = std::conjunction<std::is_convertible<types, std::string_view>...>;

template<typename... strings, class = std::enable_if_t<are_strings<strings...>::value, void>>
void func(strings... args)
{
    (std::cout << ... << args);
}

int main()
{
    const char* tmp1 = "Hello ";
    const std::string tmp2 = "World";
    const std::string_view tmp3 = "!";

    func(tmp1, tmp2, tmp3, "\n");

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这实际上按预期工作,但仍有一个大问题.


问题

只有可转换为的类std::string_view才能在此函数中使用,这很棒.
但是,即使类是可转换的,它们也不会转换为std::string_view!

这导致不必要的数据复制(例如,当std::string作为参数传递时).


有没有办法强制将可变参数隐式转换为std::string_view


注意

我知道std::initializer_list,但我想保持函数调用简单,没有{}.

Yak*_*ont 5

namespace impl{
  template<class...SVs>
  void func(SVs... svs){
    static_assert( (std::is_same< SVs, std::string_view >{} && ...) );
    // your code here
  }
}
template<class...Ts,
  std::enable_if_t< (std::is_convertible<Ts, std::string_view >{}&&...), bool > =true
>
void func( Ts&&...ts ){
  return impl::func( std::string_view{std::forward<Ts>(ts)}... );
}
Run Code Online (Sandbox Code Playgroud)

或者某些.

  • @isku转而内联,强迫非impl理想.我完美地向前转换为字符串视图.添加一些括号和带引号的字符串到编译器的静态断言是c ++ 11. (2认同)