Creación de instancias implícita de la plantilla "clase" no definida

Al intentar ofrecer funciones para los argumentos de plantilla const y non-const en mi biblioteca, me encontré con un problema extraño. El siguiente código fuente es un fenómeno de ejemplo mínimo:

#include <iostream>


template<typename some_type>
struct some_meta_class;

template<>
struct some_meta_class<int>
{
    typedef void type;
};



template<typename some_type>
struct return_type
{
    typedef typename some_meta_class< some_type >::type test;

    typedef void type;
};



template<typename type>
typename return_type<type>::type foo( type & in )
{
    std::cout << "non-const" << std::endl;
}

template<typename type>
void foo( type const & in )
{
    std::cout << "const" << std::endl;
}


int main()
{
    int i;

    int const & ciref = i;
    foo(ciref);
}

Intenté implementar una versión no constante y una versión constante para foo pero desafortunadamente este código no se compilará en CLANG 3.0 y gcc 4.6.3.

main.cpp: 18: 22: error: creación de instancias implícita de la plantilla no definida 'some_meta_class'

Por alguna razón, el compilador quiere usar la versión no constante de foo para una referencia constante. Esto obviamente conduce al error anterior porque no hay implementación para some_meta_class. Lo extraño es que si haces uno de los siguientes cambios, el código se compila bien y funciona:

descomentar / eliminar la versión no constantequitar o quitar el typedef de return_type :: test

Este ejemplo es, por supuesto, minimalista y puro académico. En mi biblioteca encontré este problema porque las versiones const y non-const devuelven tipos diferentes. Manejé este problema usando una clase auxiliar que está parcialmente especializada.

Pero, ¿por qué el ejemplo anterior resulta en un comportamiento tan extraño? ¿Por qué el compilador no quiere usar la versión no constante donde la versión constante es válida y coincide mejor?

Respuestas a la pregunta(1)

Su respuesta a la pregunta