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,但我想保持函数调用简单,没有{}.
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)
或者某些.