我有一个代码在Visual Studio 2017中编译得很好,直到今天,但现在我不断从帖子末尾提供的std::vector
获取模板实例化错误。我应该补充一点,在那时(代码编译好的时候)和现在之间没有改变过一行代码。
当我解决问题时,奇怪地归结为std::vector
是否包含在其中一个头文件中。以下代码重现错误:
(请注意,代码没有多大意义。)
CDataUnit_ALB.h:
#pragma once
#include "DataUnit\CDataUnit.h"
// #include <vector> // <== UnREM'ing this results in compile errors
class CDataUnit_ALB :
public CDataUnit
{
public:
friend
void swap(CDataUnit_ALB& lhs, CDataUnit_ALB& rhs) {
using Base_t = CDataUnit;
using std::swap;
swap(static_cast<Base_t&>(lhs), static_cast<Base_t&>(rhs));
}
};
CDataUnit.h
#pragma once
#include <memory>
template<typename Tp_Alloc = std::allocator<char>>
class basic_CDataUnit
{
public:
using allocator_type =
typename std::allocator_traits<Tp_Alloc>::template rebind_alloc<char>;
struct Representation :
public allocator_type
{
char* data;
friend
void swap(Representation& lhs, Representation& rhs) noexcept {
using std::swap;
swap<allocator_type>(lhs, rhs); // swap base members
swap(lhs.data, rhs.data);
}
};
Representation m_r;
friend
void swap(basic_CDataUnit& lhs, basic_CDataUnit& rhs) noexcept {
using std::swap;
swap(lhs.m_r, rhs.m_r);
}
};
using CDataUnit = basic_CDataUnit<>;
的main.cpp
#include "DataUnit\CDataUnit_ALB.h"
int main() {
return 0;
}
以下是我得到的编译错误:
1>------ Build started: Project: test, Configuration: Debug Win32 ------
1>CDataUnit_ALB.cpp
1>c:\[path_to_msvc]\14.11.25503\include\vector(2131): error C2039: '_Alloc': is not a member of 'std::allocator<char>'
1>c:\[path_to_msvc]\14.11.25503\include\iosfwd(628): note: see declaration of 'std::allocator<char>'
1>c:\[path_to_msvc]\14.11.25503\include\vector(2179): note: see reference to class template instantiation 'std::_Vb_iter_base<_Alvbase_wrapped>' being compiled
1> with
1> [
1> _Alvbase_wrapped=std::allocator<char>
1> ]
1>c:\[path_to_project]\cdataunit.h(20): note: see reference to class template instantiation 'std::_Vb_reference<std::allocator<char>>' being compiled
1>c:\[path_to_project]\cdataunit.h(18): note: while compiling class template member function 'void swap(basic_CDataUnit<std::allocator<char>>::Representation &,basic_CDataUnit<std::allocator<char>>::Representation &) noexcept'
1>c:\[path_to_project]\cdataunit.h(25): note: see reference to class template instantiation 'basic_CDataUnit<std::allocator<char>>::Representation' being compiled
1>c:\[path_to_project]\cdataunit_alb.h(10): note: see reference to class template instantiation 'basic_CDataUnit<std::allocator<char>>' being compiled
1>c:\[path_to_msvc]\14.11.25503\include\vector(2131): error C2061: syntax error: identifier '_Alloc'
1>c:\[path_to_msvc]\14.11.25503\include\vector(2131): error C2238: unexpected token(s) preceding ';'
1>c:\[path_to_msvc]\14.11.25503\include\vector(2132): error C2065: '_Alvbase': undeclared identifier
1>c:\[path_to_msvc]\14.11.25503\include\vector(2132): error C2923: 'std::allocator_traits': '_Alvbase' is not a valid template type argument for parameter '_Alloc'
1>c:\[path_to_msvc]\14.11.25503\include\vector(2132): error C2955: 'std::allocator_traits': use of class template requires template argument list
1>c:\[path_to_msvc]\14.11.25503\include\xmemory0(878): note: see declaration of 'std::allocator_traits'
1>c:\[path_to_msvc]\14.11.25503\include\vector(2132): error C2039: 'size_type': is not a member of 'std::allocator_traits<_Alloc>'
1>c:\[path_to_msvc]\14.11.25503\include\xmemory0(196): note: see declaration of 'std::allocator_traits<_Alloc>'
1>c:\[path_to_msvc]\14.11.25503\include\vector(2132): error C2061: syntax error: identifier 'size_type'
1>c:\[path_to_msvc]\14.11.25503\include\vector(2132): error C2238: unexpected token(s) preceding ';'
1>c:\[path_to_msvc]\14.11.25503\include\vector(2133): error C2065: '_Alvbase': undeclared identifier
1>c:\[path_to_msvc]\14.11.25503\include\vector(2133): error C2923: 'std::allocator_traits': '_Alvbase' is not a valid template type argument for parameter '_Alloc'
1>c:\[path_to_msvc]\14.11.25503\include\vector(2133): error C2955: 'std::allocator_traits': use of class template requires template argument list
1>c:\[path_to_msvc]\14.11.25503\include\xmemory0(878): note: see declaration of 'std::allocator_traits'
1>c:\[path_to_msvc]\14.11.25503\include\vector(2133): error C2039: 'difference_type': is not a member of 'std::allocator_traits<_Alloc>'
1>c:\[path_to_msvc]\14.11.25503\include\xmemory0(196): note: see declaration of 'std::allocator_traits<_Alloc>'
1>c:\[path_to_msvc]\14.11.25503\include\vector(2133): error C2061: syntax error: identifier 'difference_type'
1>c:\[path_to_msvc]\14.11.25503\include\vector(2133): error C2238: unexpected token(s) preceding ';'
1>c:\[path_to_msvc]\14.11.25503\include\vector(2134): error C2065: '_Alvbase': undeclared identifier
1>c:\[path_to_msvc]\14.11.25503\include\vector(2134): error C2923: 'std::_Rebind_alloc_t': '_Alvbase' is not a valid template type argument for parameter '_Alloc'
1>c:\[path_to_msvc]\14.11.25503\include\vector(2141): error C2061: syntax error: identifier '_Sizet'
1>c:\[path_to_msvc]\14.11.25503\include\vector(2148): error C2061: syntax error: identifier '_Sizet'
1>c:\[path_to_msvc]\14.11.25503\include\vector(2155): error C2061: syntax error: identifier '_Sizet'
1>c:\[path_to_msvc]\14.11.25503\include\vector(2172): error C3646: '_Myoff': unknown override specifier
1>c:\[path_to_msvc]\14.11.25503\include\vector(2172): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
奇怪的观察:
1-第一个错误(即error C2039: '_Alloc': is not a member of 'std::allocator<char>'
)来自类using _Alvbase = typename _Alvbase_wrapped::_Alloc;
中的typedef _Vb_iter_base
,它似乎与bool
std::vector
的特化有关。 1}}并且代码中的任何地方都不使用该特化。
2-用swap<allocator_type>(lhs, rhs);
替换CDataUnit.h中friend void swap(Representation& lhs, Representation& rhs)
中的swap(static_cast<allocator_type&>(lhs), static_cast<allocator_type&>(rhs));
似乎可以解决问题。
我很感激为什么会发生这种情况。
答案 0 :(得分:2)
考虑一下:
template<class T> struct foo : T { };
template<class T> void swap(foo<T>, foo<T>);
template<class T> void swap(T&, T&);
int i = 1, j = 2;
swap<int>(i, j);
您认为会发生什么?
main.cpp:1:36: error: base specifier must name a class
template<class T> struct foo : T { };
^
main.cpp:6:15: note: in instantiation of template class 'foo<int>' requested here
swap<int>(i, j);
^
因为您指定了一个显式模板参数,所以它被替换为重载集中每个函数模板的签名,这意味着您可以使用类模板实例化类模板,如果类模板,它们永远不会被使用用于其中一个重载的签名。
在上面的示例中,该替换触发foo<int>
的实例化,这会触发硬错误。在您的代码中,它是std::_Vb_reference<std::allocator<char>>
。
只是......不要这样做。