2012-06-02 9 views
9

El siguiente código da un error del compilador (gcc-4.7 carrera con -std=c++11): Mensaje¿Por qué no puede gcc deducir tamaño de plantilla para argumento de matriz? (C++ 11)

#include <iostream> 
#include <array> 

template <typename T, int N> 
std::ostream & operator <<(std::ostream & os, const std::array<T, N> & arr) { 
    int i; 
    for (i=0; i<N-1; ++i) 
    os << arr[i] << " "; 
    os << arr[i]; 
    return os; 
} 

int main() { 
    std::array<double, 2> lower{1.0, 1.0}; 
    std::cout << lower << std::endl; 
    return 0; 
} 

error:

tmp6.cpp: In function ‘int main()’: tmp6.cpp:16:16: error: cannot bind
‘std::ostream {aka std::basic_ostream}’ lvalue to
‘std::basic_ostream&&’ In file included from
/usr/include/c++/4.7/iostream:40:0,
from tmp6.cpp:1: /usr/include/c++/4.7/ostream:600:5: error: initializing argument 1 of ‘std::basic_ostream<_CharT,
_Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&&, const _Tp&) [with _CharT = char; _Traits = std::char_traits; _Tp = std::array]’

Cuando me libro de la declaración de función de plantilla y reemplazar T con double y con 2, compila muy bien (editar: dejando T y reemplazando N con 2 trabajos, pero especificar N=2 como el argumento predeterminado para N no funciona.).

  1. ¿Alguien sabe por qué gcc no puede enlazar esto automáticamente?
  2. ¿Cuál sería la sintaxis para llamar al operador << con parámetros de plantilla explícitamente especificados?

respuesta a la pregunta 2:operator<<<double, 2>(std::cout, lower);

Editar: Esto también es cierto para la siguiente función, que sólo se templated en el tamaño de la matriz:

template <int N> 
void print(const std::array<double, N> & arr) { 
    std::cout << "print array here" << std::endl; 
} 

int main() { 
    std::array<double, 2> lower{1.0, 1.0}; 
    print<2>(lower); // this works 
    print(lower); // this does NOT work 
    return 0; 
} 

Gracias una mucho por tu ayuda.

+1

Tenga en cuenta que no debe definir 'operator <<' para un tipo estándar. –

+0

@ K-ballo ¿Alguna idea de cómo responder a alguna de las dos preguntas numeradas en la publicación? – user

+0

Si pudiera responder, habría puesto una respuesta en lugar de un comentario ... El problema probablemente proviene de la implementación incorrecta de los operadores. –

Respuesta

12

Tenga en cuenta su declaración:

template <typename T, int N> 
std::ostream & operator <<(std::ostream & os, const std::array<T, N> & arr) { 

La definición para std::array es:

template<typename T, std::size_t N> class array {...}; 

Está usando int en su lugar o f std::size_t, y es por eso que no coincide .

+0

Enorme +1. Muchas gracias, no estoy seguro de que * nunca * hubiera encontrado eso. – user

+0

+1 Estaba leyendo qué estándar (14.8.2) dice acerca de la deducción de la plantilla y se preguntó qué he omitido, porque no había nada en contra de este tipo de deducción. El tipo incorrecto en la definición de la plantilla también me atrapó. –

1

Puede llamar operator<< con los parámetros de plantilla se especifica en esta, no tan aestethic, así:

operator<< <double,2>(std::cout, lower) << std::endl; 
+0

+1 No sé por qué no intenté eso-- Estaba tan obsesionado con el '<<<' que no lo hice ¡Creo que al compilador le gustaría (creo que estaba proyectando)! – user

Cuestiones relacionadas