1

考虑以下示例。

#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++ 标准)?为什么会发生,我该如何解决?

编辑

解决方法是在 中创建正确的类型foo

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

但问题仍然存在:为什么它不是自动创建的?

4

3 回答 3

5
return boo( a );

这里 type ofaint,并且没有 nameboo接受 type 参数的函数int。因此,您会看到此错误:

dfg.cpp:25: 错误: 没有匹配函数调用'boo(int)'</p>

即使int可以隐式转换为boost::optional<int>,编译器也无法boost::optional<T>从调用站点推导出模板参数。这是您明确需要将类型提及为的非推断上下文之一,

   return boo<A>(a);

该标准在 14.8.2.1 美元中说,

如果模板参数未在函数模板的任何函数参数中使用,或者仅在非推导上下文中使用,则不能从函数调用中推导出其对应的模板参数,并且模板参数必须显式指定

于 2011-02-09T16:29:32.133 回答
2

要解决此问题,您需要在调用时明确指定类型boo,即

return boo<A>( a );

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

编辑:删除我的解释,这是垃圾,纳瓦兹的解释更好..

于 2011-02-09T16:32:48.377 回答
1

您假设因为optional<int>有一个来自 int 的隐式构造函数,编译器应该知道这是您尝试创建的类型。

模板类型扣除不延伸到那个。

您可以编写自己的 boo 模板,该模板将可选作为泛化

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
}
于 2011-02-09T16:51:41.170 回答