与可变模板的罕见错误? [英] Rare bug with variadic templates?
问题描述
我在程序中使用了可变参数模板,它出现了意外的错误。我孤立的错误,我震惊了它:
I were using variadic templates in a program and it's come up an unexpected error. I isolated the error and I has shocked it:
#include<cctype>
#include<iostream> // try to delete this line
class A
{
public:
void constructor()
{ }
template<typename... Args>
void constructor( int (*f)(int), Args... args )
{
// process( f )
constructor( args... );
}
template<typename... Args>
A( Args... args )
{
constructor( args... );
}
};
int main()
{
A a;
a.constructor( std::isspace ); // ok
A b( std::isspace ); // error
return 0;
}
如果删除#include iostream行, 。然而,如果你把这一行,编译器抛出一个错误:
If you delete the line "#include iostream", the source is compiled alright. However, if you put this line, the compiler throw an error:
prov.cpp: In function ‘int main()’:
prov.cpp:32:22: error: no matching function for call to ‘A::A(<unresolved overloaded function type>)’
prov.cpp:32:22: note: candidates are:
prov.cpp:18:7: note: A::A(Args ...) [with Args = {}]
prov.cpp:18:7: note: candidate expects 0 arguments, 1 provided
prov.cpp:4:7: note: constexpr A::A(const A&)
prov.cpp:4:7: note: no known conversion for argument 1 from ‘<unresolved overloaded function type>’ to ‘const A&’
prov.cpp:4:7: note: constexpr A::A(A&&)
prov.cpp:4:7: note: no known conversion for argument 1 from ‘<unresolved overloaded function type>’ to ‘A&&’
b $ b
我使用这个g ++版本:g ++(Ubuntu / Linaro 4.7.2-11precise2)4.7.2
,我用这个标志编译: g ++ -Wall -pedantic -std = c ++ 11 prov.cpp -o prov
我不明白为什么编译器抛出这个错误。
I don't understand why compiler throws this error. Is it a possible bug?
推荐答案
问题是< cctype>
定义单个函数 isspace
,但添加< iostream>
会为< locale> 中拉入的isspacepaceisspace =nofollow> isspace
< cctype>
中的一个是
The problem is that <cctype>
defines a single function isspace
, but adding <iostream>
adds another overload for isspace
that is pulled in from <locale>
. The one from <cctype>
is
int isspace( int ch );
< locale>
template< class charT >
bool isspace( charT ch, const locale& loc );
同时包含 std :: isspace
变得模糊,因此您的代码失败。这只有当你通过你的真正的ctor(而不是构造函数
),因为编译器不能决定什么转发。 OTOH,方法构造函数
接受一个参数,它已经告诉编译器如何从两个重载中选择
With both included, the std::isspace
becomes ambiguous and hence your code fails. This becomes visible only when you route it through your real ctor (instead of constructor
) because then the compiler can't decide what to forward. OTOH, the method constructor
takes a parameter which already tells the compiler how to choose from both overloads.
这篇关于与可变模板的罕见错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!