2013-07-05 5 views
1

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

#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> >&&’ 

ответ

3

Это most vexing parse:

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

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

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

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

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

это ошибка в GCC или это нормально? – Vincent

+0

@ Vincent: Это нормально (и знаменито известное как [* Самое неприятное разбор *) (http://en.wikipedia.org/wiki/Most_vexing_parse)) в соответствии со стандартом C++. –

0

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

3

Работает с:

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

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

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

быть функция.

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

+2

Заслуживает внимания: используйте инициализатор 11-стилевого кода C++ => сэкономит много проблем, включая предостережение о том, чтобы объявить функцию, где вы хотите построить объект. – xtofl

 Смежные вопросы

  • Нет связанных вопросов^_^