Можно ли передать переменную шаблон в функцию через лямбду?

Как я знаю, как передать шаблонную функцию в качестве аргумента шаблона, Я сейчас изо всех сил пытаюсь передать переменную шаблон таким же образом.

Вот минимальный пример того, что я пробовал:

#define PASS_VARIABLE_TEMPLATE(name) [dummy=nullptr](auto&&...args) \
{return name<decltype(args)...>;}

//testing
template <typename T>
bool value = std::is_fundamental<T>::value;

template <typename Hax>
void print_bool(Hax h)
{
std::cout << h(int{}) << std::endl; // no error, wrong output
//std::cout << h(int{}, float{}) << std::endl; // error, good
}

int main()
{
print_bool(PASS_VARIABLE_TEMPLATE(value)); //prints 0 instead of 1
}

демонстрация

Если он компилируется, то почему вывод неправильный?

3

Решение

template<class T>struct tag_t{using type=T; constexpr tag_t(){}};
template<class Tag>using tagged_type=typename Tag::type;
template<class T>constexpr tag_t<T> tag{};

Они помогают передавать типы как значения и распаковывать их.

#define PASS_VARIABLE_TEMPLATE(name) [](auto...args) \
{return name<tagged_type<decltype(args)>...>;}

внутри print_bool ты сделаешь:

std::cout << h(tag<int>) << std::endl;

Не уверен, почему вы делаете dummy=nullptr вещь.

tag В качестве шаблона можно отнести типы unmolested.

1

Другие решения

Основная проблема с вашим кодом заключается в том, что decltype выводит аргументы как rvalue ссылка (int&&) потому что ваша лямбда использует пересылка ссылок принять аргументы.
std::is_fundamental будет хорошо работать с голый тип.

Для вашего конкретного фрагмента правильное решение удалить ссылку.

#define PASS_VARIABLE_TEMPLATE(name) \
[dummy=nullptr](auto&&...args){return name<std::remove_reference_t<decltype(args)>...>;}

Теперь это работает. 🙂 Видеть это Жить на Колиру


Немного более или лучше общий способ будет дополнительно удалить резюме классификаторы. В конце концов, вы можете использовать std::decay

#define PASS_VARIABLE_TEMPLATE(name) [dummy=nullptr](auto&&...args) \
{return name<std::decay_t<decltype(args)>...>;}
3

По вопросам рекламы [email protected]