Ошибка вариативного шаблона: "В экземпляре" (gcc 9.2)
Я изучаю вариативный шаблон на С ++17 на YouTube-канале Джейсона Тернера, а затем копирую его примерный код (показан ниже). В своем видео он использует сайт https://godbolt.org/ с gcc 7.
#include <utility>
template<typename ... B>
struct Merged : B ... {
template<typename ... T>
Merged(T&& ... t) : B(std::forward<T>(t))... {}
using B::operator()...;
};
template<typename ... T>
Merged(T...) -> Merged<std::decay_t<T>...>;
int main() {
const auto l1 = []() { return 4; };
const auto l2 = [](const int i) { return i * 10; };
Merged merged(l1,
l2,
[](const double d) { return d * 3.2; });
return 0;
}
Я попробовал код на своем компьютере с gcc 9.2 и получил следующую ошибку:
При создании экземпляра 'Merged::Merged(T&& ...) (с T = {const main()::&, const main()::&, main()::}; B = {}]':
Я попытался использовать сайт Godbolt, чтобы проверить это, но он также не компилируется (с gcc 7.1 и gcc 9.2) и выдает больше ошибок, например:
ошибка: отсутствуют аргументы шаблона перед 'объединением' Объединенный объединенный (l1,
а также
ошибка: ожидалось первичное выражение перед токеном ')' [](const double d) { return d * 3.2; });
Что означает эта ошибка и что мне нужно сделать, чтобы ее исправить?
Скомпилируйте строку на моем компьютере:
g++ -Wall -fexceptions -O2 -pedantic -Wextra -Wall -std=c++1z -m64 -c /home/thearquitect/Desktop/C++/variadic.cpp -o ~/Desktop/obj/variadic.o
g++ -o ~/Desktop/bin/variadic ~/Desktop/obj/variadic.o -s -m64
1 ответ
Что означает эта ошибка и что мне нужно сделать, чтобы ее исправить?
Насколько я понимаю, в вашем коде нет ничего плохого.
Подозреваю ошибку g++.
Чтобы исправить это... ну... обойти это... не спрашивайте меня, почему, но я вижу, что это работает для обоих компиляторов, требуется первый параметр шаблона перед списком переменных, для Merged
.
Я имею в виду: следующее struct
template <typename B0, typename ... B>
struct Merged : public B0, public B ...
{
template <typename T0, typename ... T>
Merged (T0 && t0, T && ... t)
: B0{std::forward<T0>(t0)}, B{std::forward<T>(t)}...
{ }
using B0::operator();
using B::operator()...;
};
вместе со следующим руководством по выводам
template <typename T0, typename ... T>
Merged (T0, T ...)
-> Merged<std::decay_t<T0>, std::decay_t<T>...>;
работает с обоими компиляторами.
Также ваше оригинальное руководство по дедукции работает с модифицированным struct
.
-- РЕДАКТИРОВАТЬ --
Я вижу, что вы также можете решить проблему (компиляция с обоими компиляторами), поддерживая struct
только с вариативным списком
template <typename ... B>
struct Merged: public B ...
{
template <typename ... T>
Merged (T && ... t)
: B{std::forward<T>(t)}...
{ }
using B::operator()...;
};
и используя руководство по дедукции с обязательным аргументом
template <typename T0, typename ... T>
Merged (T0, T ...)
-> Merged<std::decay_t<T0>, std::decay_t<T>...>;