Сбой при поиске в шаблоне - PullRequest
1 голос
/ 09 февраля 2011

Рассмотрим следующий пример.

#include <iostream>
#include <boost/optional.hpp>

template < typename A >
int boo( const boost::optional< A > &a );

template < typename A >
int foo( const A &a )
{
    return boo( a );
}

template < typename A >
int boo( const boost::optional< A > & )
{
    return 3;
}


int main()
{
    std::cout << "foo = " << foo( 3 ) << std::endl;
    std::cout << "boo = " << boo( 3 ) << std::endl;
}

Компиляция с использованием g ++ 4.3.0 выдает следующие ошибки компиляции:

dfg.cpp: In function ‘int main()’:
dfg.cpp:25: error: no matching function for call to ‘boo(int)’
dfg.cpp: In function ‘int foo(const A&) [with A = int]’:
dfg.cpp:24:   instantiated from here
dfg.cpp:12: error: no matching function for call to ‘boo(const int&)’

Что я должен делать по-другому (если это возможно со ссылками из стандарта C ++)? Почему это происходит и как мне это исправить?

EDIT

Исправление - создать правильный тип в foo:

template < typename A >
int foo( const A &a )
{
    const boost::optional< A > optA( a );
    return boo( optA );
}

Но все еще остается вопрос: почему он не создается автоматически?

Ответы [ 3 ]

5 голосов
/ 09 февраля 2011
return boo( a );

Здесь тип a равен int, и нет функции с именем boo, которая принимает аргумент типа int.Следовательно, вы видите эту ошибку:

dfg.cpp: 25: ошибка: нет соответствующей функции для вызова 'boo (int)'

Даже если int можетБудучи неявно преобразованным в boost::optional<int>, компилятор не сможет определить аргумент шаблона для boost::optional<T> из вызывающего сайта.Это один из не выводимых контекстов, где вам явно нужно упомянуть тип как

   return boo<A>(a);

Стандарт говорит в $ 14.8.2.1,

если параметр шаблона не используется ни в одном из параметров функции шаблона функции или используется только в недедуцированном контексте, его соответствующий аргумент шаблона не может быть выведен из вызова функции и аргумента шаблонадолжен быть явно указан .

2 голосов
/ 09 февраля 2011

Чтобы это исправить, вам нужно явно указать тип при вызове boo, то есть

return boo<A>( a );

и

std::cout << "boo = " << boo<int>( 3 ) << std::endl;

РЕДАКТИРОВАТЬ: удалил мое объяснение, это был мусор,Объяснение Наваза лучше ..

1 голос
/ 09 февраля 2011

Вы предполагаете, что, поскольку optional<int> имеет неявный конструктор из int, компилятор должен знать, что это тип, который вы пытаетесь создать.

Вывод типа шаблона не распространяется на это.

Вы можете написать свой собственный шаблон бу с тем, который принимает необязательный как обобщение

template< typename A > int boo( const A& a );
template < typename A >
int boo( const boost::optional< A > & )
{
    return 3;
}

template < typename A >
int boo( const A & a )
{
    return boo<A>(boost::optional(a)); // allows implicit conversion
}
...