以下是一个完美运行的代码示例:
#include#include template< class D, template< class D, class A > class C, class A = std::allocator< D > > void foo( C< D, A > *bar, C< D, A > *bas ) { std::cout << "Ok!" << std::endl; } int main( ) { std::vector< int > *sample1 = nullptr; std::vector< int > *sample2 = nullptr; foo( sample1, sample2 ); return( 0 ); }
但是,在下面的代码中,编译器无法将std :: vector
#include#include template< class D, template< class D, class A > class C, class A = std::allocator< D > > void foo( C< D, A > *bar, C< D, A > *bas ) { std::cout << "Ok!" << std::endl; } int main( ) { std::vector< int > *sample = nullptr; foo( sample, nullptr ); return( 0 ); }
错误消息是:
$ g++ -std=c++11 nullptr.cpp -o nullptr nullptr.cpp: In function ‘int main()’: nullptr.cpp:11:24: error: no matching function for call to ‘foo(std::vector*&, std::nullptr_t)’ foo( sample, nullptr ); nullptr.cpp:11:24: note: candidate is: nullptr.cpp:5:6: note: template class C, class A> void foo(C *, C *) void foo( C< D, A > *bar, C< D, A > *bas ) { nullptr.cpp:5:6: note: template argument deduction/substitution failed: nullptr.cpp:11:24: note: mismatched types ‘C *’ and ‘std::nullptr_t’ foo( sample, nullptr );
为什么会这样?
这就是模板推理的工作方式:不进行转换.
这个问题也不是特有的nullptr
,考虑到极其简单的情况:
#include <iostream> struct Thing { operator int() const { return 0; } } thingy; template <typename T> void print(T l, T r) { std::cout << l << " " << r << "\n"; } int main() { int i = 0; print(i, thingy); return 0; }
其中收益率:
prog.cpp: In function ‘int main()’: prog.cpp:12:17: error: no matching function for call to ‘print(int&, Thing&)’ print(i, thingy); ^ prog.cpp:12:17: note: candidate is: prog.cpp:8:6: note: template<class T> void print(T, T) void print(T l, T r) { std::cout << l << " " << r << "\n"; } ^ prog.cpp:8:6: note: template argument deduction/substitution failed: prog.cpp:12:17: note: deduced conflicting types for parameter ‘T’ (‘int’ and ‘Thing’) print(i, thingy); ^
因此,转换nullptr
到int*
不发生前向模板参数推导任一.如上所述,您有两种解决问题的方法:
指定模板参数(因此不会发生扣减)
自己转换参数(扣除发生,但在显式转换后)
从C++标准(4.10指针转换[conv.ptr])
1空指针常量是整数类型的整数常量表达式(5.19)prvalue,其计算结果为零或类型为std :: nullptr_t的prvalue.空指针常量可以转换为指针类型; 结果是该类型的空指针值,并且可以与对象指针或函数指针类型的每个其他值区分开.这种转换称为空指针转换.
在您的第一个例子中,您的两个nullptr已经在模板参数推断之前被转换.所以没有问题,你有两次相同的类型.
在第二个中,有一个std::vector<int>
和一个std::nullptr_t
不匹配.你必须自己做转换:static_cast<std::vector<int>*>(nullptr)
.