Ошибка шаблона Variadi c: «В экземпляре» (g cc 9.2) - PullRequest
2 голосов
/ 07 марта 2020

Я узнаю о шаблоне variadi c на c ++ 17 на канале youtube Джейсона Тернера , затем копирую его пример кода (показан ниже). В своем видео он использует сайт godbolt.org с g cc 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;
}

Я попробовал код на своем компьютере с g cc 9.2 и получил следующая ошибка:

В экземпляре 'Merged :: Merged (T && ...) (с T = {const main () :: &, const main () :: &, main ( ) ::}; B = {}] ':

Я пытался использовать сайт Godbolt, чтобы проверить его, но он также не компилируется (с g cc 7.1 и g cc 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

Godbolt try

1 Ответ

1 голос
/ 07 марта 2020

Что означает эта ошибка и что мне нужно сделать, чтобы исправить ее?

В вашем коде нет ничего плохого, насколько я понимаю.

Я подозреваю, что g ++ ошибка.

Чтобы исправить это ... хорошо ... к go вокруг него ... не спрашивайте меня, почему, но я вижу, что для обоих компиляторов работает, требуется первый параметр шаблона, прежде чем список variadi c для 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.

- EDIT -

Я вижу, что Вы также можете решить проблему (компиляция с обоими компиляторами), поддерживая struct только с списком переменных c

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>...>;
...