#c #templates #parameter-pack
#c #шаблоны #пакет параметров
Вопрос:
Я новичок в шаблонах, особенно с пакетом параметров, и мне интересно, смогу ли я получить первое значение из пакета.
Например, следующий код:
template <typename T, typename... Args>
bool register(Args... args) {
if (!Foo<T>(args..) {
assert(std::is_same_v<std::string, args...[0]>);
std::cerr << "Failed call Foo with " args...[0] "n";
}
}
Как мне действительно получить первое значение args...
?
Стоит отметить, что args..
. может содержать различные типы (string, boolean и т.д.)
Комментарии:
1. Есть ли что-то, что мешает вам попробовать это самостоятельно и посмотреть, так ли это на самом деле?
Ответ №1:
Более простой в вашем случае, похоже, меняет вашу функцию на:
template <typename T, typename Arg, typename... Args>
bool register(Arg arg, Args... args) {
if (!Foo<T>(arg, args...) {
assert(std::is_same_v<std::string, Arg>);
std::cerr << "Failed call Foo with " arg "n";
}
}
и из утверждения, даже
template <typename T, typename... Args>
bool register(const std::stringamp; s, Args... args) {
if (!Foo<T>(s, args...) {
std::cerr << "Failed call Foo with " s "n";
}
}
else <tuple>
предоставляет несколько полезных инструментов:
template <typename T, typename Arg, typename... Args>
bool register(Args... args) {
if (!Foo<T>(args...) {
assert(std::is_same_v<std::string,
std::tuple_element_t<0, std::tuple<Args...>>);
std::cerr << "Failed call Foo with "
std::get<0>(std::tie(args...)) "n";
}
}
Ответ №2:
Вы можете использовать lambda для извлечения первого параметра:
template<typename T, typename... Args>
bool register(Args... args) {
if (!Foo<T>(args...)) {
autoamp; first = [](autoamp; first, ...) -> autoamp; { return first; }(args...);
static_assert(std::is_same_v<std::string,
std::remove_reference_t<decltype(first)>>);
std::cerr << "Failed call Foo with " first "n";
}
}
Ответ №3:
Обычно я использую решение, описанное выше, просто добавляю явный дополнительный параметр шаблона для первого параметра. Если вы не можете этого сделать, это тоже работает :
#include <type_traits>
namespace details
{
template<typename type_t, typename... args_t>
struct deduce_first
{
using type = type_t;
};
}
template<typename... args_t>
using first_t = typename details::deduce_first<args_t...>::type;
template<typename... args_t>
bool register_f(args_tamp;amp;... args)
{
static_assert(std::is_same_v<first_t<args_t...>, bool>, "first argument should have type bool");
return true;
}
int main()
{
register_f(true, 1.0);
// register_f(1.0); <== does indeed not complie
return 0;
}