可变模板的罕见错误
Rare bug with variadic templates?
本文关键字:错误 更新时间:2023-10-16
我在一个程序中使用可变模板,出现了一个意想不到的错误。我隔离了错误,并对其进行了处理:
#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"这行,源代码就编译好了。但是,如果您输入这一行,编译器会抛出一个错误:
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&&’
我正在使用这个g++版本:g++ (Ubuntu/Linaro 4.7.2-11precise2) 4.7.2我正在编译这个标志:g++ -Wall -pedantic -std=c++11 prov.cpp -o prov
我不明白为什么编译器会抛出这个错误。这可能是一个bug吗?
这不是编译器的错误,甚至不是可变模板的问题,std::isspace
只是超载了。当直接调用.constructor
时,第一个参数int (*f)(int)
为编译器提供了足够的信息来选择正确的过载,而泛型参数则没有。这很容易用一个例子来演示:
// our std::isspace
void foo(int){}
void foo(double){}
void test1(void (*f)(int)){}
template<class T>
void test2(T v){}
int main(){
test1(foo); // compiles, compiler sees you want the 'int' overload
test2(foo); // error, compiler has no clue which overload you want
// and which type to deduce 'T' as
}
您可以通过两种方式修复此问题:
int (*f)(int) = std::isspace; // assign to variable, giving the compiler the information
A b(f); // already has concrete type here
// or
A b(static_cast<int(*)(int)>(std::isspace)); // basically the same as above, in one step
问题是<cctype>
定义了单个函数isspace
,但是添加<iostream>
会为isspace
添加另一个重载,该重载是从<locale>
拉进来的。<cctype>
中的是
int isspace( int ch );
<locale>
中的
template< class charT >
bool isspace( charT ch, const locale& loc );
如果两者都包含,那么std::isspace
就会变得模棱两可,从而导致代码失败。只有当您通过真正的actor(而不是constructor
)路由它时,这才会变得可见,因为编译器无法决定转发什么。方法constructor
接受了一个参数,该参数已经告诉编译器如何从两个重载中进行选择。
相关文章:
- 警告处理为错误这里有什么问题
- "error: no matching function for call to"构造函数错误
- boost::进程间消息队列引发错误
- C++,OpenCV,尝试显示图像时"OpenCV(4.3.0) Error: Assertion failed (size.width>0 && size.height>0)"此错误
- 有关插入适配器的错误。[错误]请求从 'back_insert_iterator<vector<>>' 类型转换为非标量类型
- QT在错误的班级中寻找空位
- vector.resize()中的分配错误
- 代码在main()中运行,但在函数中出现错误
- 释放错误后堆使用
- (C++)分析树以计算返回错误值的简单算术表达式
- Project Euler问题4的错误解决方案
- 我的字符计数代码计算错误.为什么
- 从"int*"强制转换为"unsigned int"会丢失精度错误
- 尝试导入pybind-opencv模块时出现libgtk错误
- CMake项目Boost库错误:Boost/config/compiler/gcc.hpp:165:10:致命错误:cs
- 在某些循环内使用vector.push_back时出现分段错误
- MSVC多行宏编译器错误
- 静态数据成员的问题-修复链接错误会导致编译器错误
- 为什么在运行时没有向我们提供有关分段错误的更多信息?
- 错误:未在此范围内声明'reverse'