Невозможно скопировать объект, созданный из массива, созданного по умолчанию

После 1 или 2 часов, потраченных на изоляцию ошибки компиляции в окружении метапрограммирования, генерирующего ужасные сообщения компиляции, вот минимальный и простой пример, который иллюстрирует мою проблему:

#include <iostream>
#include <type_traits>
#include <array>
#include <utility>
#include <tuple>

template <class Crtp, class... Types>
struct Base
{
Base(const Types&... rhs) :
data(std::forward_as_tuple(rhs...)) {;}
std::tuple<Types...> data;
};

struct Derived
: public Base<Derived, std::array<double, 3>>
{
template <class... Args>
Derived(Args&&... args) :
Base<Derived, std::array<double, 3>>(std::forward<Args>(args)...) {;}
};

int main(int argc, char* argv[])
{
Derived a(std::array<double, 3>({{1, 2, 3}}));
Derived b(a);
Derived c(std::array<double, 3>());
Derived d(c); // Not working : why ?
return 0;
}

Это скомпилировано с g ++ 4.8.1, и я не понимаю, почему компилятор жалуется, когда я пытаюсь скопировать c в d и не a в b,

Вот ошибка:

main.cpp: In instantiation of ‘Derived::Derived(Args&& ...) [with Args = {Derived (&)(std::array<double, 3ul> (*)())}]’:
main.cpp:28:16:   required from here
main.cpp:20:73: error: no matching function for call to ‘Base<Derived, std::array<double, 3ul> >::Base(Derived (&)(std::array<double, 3ul> (*)()))’
Base<Derived, std::array<double, 3>>(std::forward<Args>(args)...) {;}
^
main.cpp:20:73: note: candidates are:
main.cpp:10:5: note: Base<Crtp, Types>::Base(const Types& ...) [with Crtp = Derived; Types = {std::array<double, 3ul>}]
Base(const Types&... rhs) :
^
main.cpp:10:5: note:   no known conversion for argument 1 from ‘Derived(std::array<double, 3ul> (*)())’ to ‘const std::array<double, 3ul>&’
main.cpp:8:8: note: constexpr Base<Derived, std::array<double, 3ul> >::Base(const Base<Derived, std::array<double, 3ul> >&)
struct Base
^
main.cpp:8:8: note:   no known conversion for argument 1 from ‘Derived(std::array<double, 3ul> (*)())’ to ‘const Base<Derived, std::array<double, 3ul> >&’
main.cpp:8:8: note: constexpr Base<Derived, std::array<double, 3ul> >::Base(Base<Derived, std::array<double, 3ul> >&&)
main.cpp:8:8: note:   no known conversion for argument 1 from ‘Derived(std::array<double, 3ul> (*)())’ to ‘Base<Derived, std::array<double, 3ul> >&&’

1

Решение

Это самый неприятный разбор:

Derived c(std::array<double, 3>());

это объявление функции c который возвращает Derived и принимает один безымянный аргумент типа указатель на функцию, которая не принимает аргументов и возвращает std::array<double, 3>.
Следовательно Derived d(c) пытается позвонить Derived конструктор из функции c, Это то, что GCC говорит здесь:

main.cpp: In instantiation of ‘Derived::Derived(Args&& ...) [with Args = {Derived (&)(std::array<double, 3ul> (*)())}]’:

Попробуй это:

Derived c{std::array<double, 3>{}};
3

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

Работает с:

Derived c(std::array<double, 3> {});

Компилятор считает параметр в

Derived c(std::array<double, 3>());

быть функцией.

Clang выдает предупреждение за это:
!!warning: parentheses were disambiguated as a function declarator.

3

Сначала сделайте ваш производный конструктор явным.
Если это не поможет добавить конструктор копирования, но я не думаю, что это потребуется

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