为什么我需要在以下示例中在 block_cache.h 之前包含 block_cache_key.h 和 block.h
Why I need to include block_cache_key.h and block.h before block_cache.h in the following example?
通常我们会使用标准类型作为std::unordered_map<key, value>
的键和值。但是现在我需要自定义自己的键和值类。
键类在block_cache_key.h
中定义如下:
#ifndef BLOCK_CACHE_KEY_H_
#define BLOCK_CACHE_KEY_H_
#include <functional>
namespace wcg{
class BlockCacheKey{
public:
BlockCacheKey(const std::string &name, int64_t offset) : name_(name), offset_(offset) {}
bool operator==(const BlockCacheKey &other) const{
return offset_ == other.offset_ && name_ == other.name_;
}
const std::string &name() const{
return name_;
}
const int64_t offset() const{
return offset_;
}
std::string to_string() const{
return name_ + "_" + std::to_string(offset_);
}
private:
std::string name_;
int64_t offset_;
};
}
namespace std{
template <>
class hash<wcg::BlockCacheKey>{
public:
size_t operator()(const wcg::BlockCacheKey &key) const{
return std::hash<std::string>()(key.name()) ^ (std::hash<int64_t>()(key.offset()));
}
};
}
#endif
值类在block.h
中定义如下:
#ifndef BLOCK_H_
#define BLOCK_H_
namespace wcg{
class Block{
public:
Block() {}
};
}
#endif
使用std::unorded_map
的类在block_cache.h
中定义如下:
#ifndef BLOCK_CACHE_H_
#define BLOCK_CACHE_H_
#include <iostream>
#include <memory>
#include <unordered_map>
namespace wcg{
class BlockCacheKey;
class Block;
class BlockCache{
public:
BlockCache() : count_(0) {
std::cout << "initial stats: " << to_string() << std::endl;
}
~BlockCache(){
std::cout << "final stats: " << to_string() << std::endl;
}
void CacheBlock(const BlockCacheKey &key, std::shared_ptr<Block> block){
std::cout << "cache put: " << key.to_string() << std::endl;
map_[key] = block;
count_++;
}
std::shared_ptr<Block> GetBlock(const BlockCacheKey &key){
auto pos = map_.find(key);
if(pos != map_.end()){
std::cout << "cache get: " << key.to_string() << std::endl;
return pos->second;
}
return nullptr;
}
std::string to_string() const{
return "block count: " + std::to_string(count_);
}
private:
std::unordered_map<BlockCacheKey, std::shared_ptr<Block>> map_;
int count_;
};
}
#endif
main 函数在main.cpp
中定义如下:
#include <memory>
#include "block_cache_key.h"
#include "block.h"
#include "block_cache.h"
// g++ -std=c++11 -g -Wall main.cpp
int main(int argc, char* argv[]){
wcg::BlockCache bc;
return 0;
}
当#include "block_cache.h"
终于结束时,编译是可以的。但是当#include "block_cache.h"
在#include "block_cache_key.h"
和#include "block.h"
之前时,编译会失败,错误消息非常丑陋,很难理解。
我已经知道的,std::unordered_map
是一个模板。 当GCC编译时,它将首先预处理包含部分,即将它们全部展开。 这给我的印象是,包含顺序不会是一个问题。
最后要注意的是,我不想在block_cache.h
中包含block_cache_key.h
和block.h
部分编译错误消息: (整个错误消息以 https://paste.ubuntu.com/p/VyrWKCTG4q/为单位(
In file included from /usr/include/c++/7/bits/hashtable.h:35:0,
from /usr/include/c++/7/unordered_map:47,
from block_cache.h:13,
from main.cpp:5:
/usr/include/c++/7/bits/hashtable_policy.h: In instantiation of 'struct std::__detail::__is_noexcept_hash<wcg::BlockCacheKey, std::hash<wcg::BlockCacheKey> >':
/usr/include/c++/7/type_traits:143:12: required from 'struct std::__and_<std::__is_fast_hash<std::hash<wcg::BlockCacheKey> >, std::__detail::__is_noexcept_hash<wcg::BlockCacheKey, std::hash<wcg::BlockCacheKey> > >'
/usr/include/c++/7/type_traits:154:31: required from 'struct std::__not_<std::__and_<std::__is_fast_hash<std::hash<wcg::BlockCacheKey> >, std::__detail::__is_noexcept_hash<wcg::BlockCacheKey, std::hash<wcg::BlockCacheKey> > > >'
/usr/include/c++/7/bits/unordered_map.h:103:66: required from 'class std::unordered_map<wcg::BlockCacheKey, std::shared_ptr<wcg::Block> >'
block_cache.h:50:60: required from here
/usr/include/c++/7/bits/hashtable_policy.h:87:34: error: no match for call to '(const std::hash<wcg::BlockCacheKey>) (const wcg::BlockCacheKey&)'
noexcept(declval<const _Hash&>()(declval<const _Key&>()))>
~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/7/bits/move.h:54:0,
from /usr/include/c++/7/bits/stl_pair.h:59,
from /usr/include/c++/7/bits/stl_algobase.h:64,
from /usr/include/c++/7/memory:62,
from main.cpp:3:
/usr/include/c++/7/type_traits: In instantiation of 'struct std::__not_<std::__and_<std::__is_fast_hash<std::hash<wcg::BlockCacheKey> >, std::__detail::__is_noexcept_hash<wcg::BlockCacheKey, std::hash<wcg::BlockCacheKey> > > >':
/usr/include/c++/7/bits/unordered_map.h:103:66: required from 'class std::unordered_map<wcg::BlockCacheKey, std::shared_ptr<wcg::Block> >'
block_cache.h:50:60: required from here
/usr/include/c++/7/type_traits:154:31: error: 'value' is not a member of 'std::__and_<std::__is_fast_hash<std::hash<wcg::BlockCacheKey> >, std::__detail::__is_noexcept_hash<wcg::BlockCacheKey, std::hash<wcg::BlockCacheKey> > >'
: public __bool_constant<!bool(_Pp::value)>
^~~~~~~~~~~~~~~~
In file included from /usr/include/c++/7/unordered_map:48:0,
from block_cache.h:13,
from main.cpp:5:
/usr/include/c++/7/bits/unordered_map.h: In instantiation of 'class std::unordered_map<wcg::BlockCacheKey, std::shared_ptr<wcg::Block> >':
block_cache.h:50:60: required from here
/usr/include/c++/7/bits/unordered_map.h:103:66: error: 'value' is not a member of 'std::__not_<std::__and_<std::__is_fast_hash<std::hash<wcg::BlockCacheKey> >, std::__detail::__is_noexcept_hash<wcg::BlockCacheKey, std::hash<wcg::BlockCacheKey> > > >'
typedef __umap_hashtable<_Key, _Tp, _Hash, _Pred, _Alloc> _Hashtable;
^~~~~~~~~~
/usr/include/c++/7/bits/unordered_map.h:110:45: error: 'value' is not a member of 'std::__not_<std::__and_<std::__is_fast_hash<std::hash<wcg::BlockCacheKey> >, std::__detail::__is_noexcept_hash<wcg::BlockCacheKey, std::hash<wcg::BlockCacheKey> > > >'
typedef typename _Hashtable::key_type key_type;
让我们看看BlockCache.h
.您向编译器保证Block
和BlockCacheKey
存在并最终将定义 - 此时它们是不完整的类型。这是可以的,只要您不以要求它们完整的方式使用它们就可以正常工作:形成对不完整类型的引用、指针甚至std::shared_ptr
s都可以。请参阅此处,列出您不得对它们做的事情。
在std::unordered_map<BlockCacheKey, std::shared_ptr<Block>>
中使用BlockCacheKey
(和Block
(违反了这一点 - 要实例化std::unordered_map<Key, Value>
模板(这是声明该类型成员所必需的(,Key
和Value
类型必须完整。
想象一下,sizeof(std::unordered_map<Key, Value>)
依赖于sizeof(Key)
(这将在其权利范围内(。只有前向声明Key
,sizeof(Key)
将是未知的,因此sizeof(std::unordered_map<Key, Value>)
将是未知的,因此您的BlockCache
的大小将是未知的(即使在您定义它之后!编译器不能使用它,这就是为什么不允许你这样做的原因。
最后要注意的是,我不想在block_cache.h中包含block_cache_key.h和block.h
这是不可能的(正如您所观察到的那样,不需要用户进行时髦的包含订单(。要实例化std::map<BlockCacheKey, Whatever>
,必须知道BlockCacheKey
的定义,您只能通过包含其标头来获得。我确实相信对于您打算用作地图值类型的std::shared_ptr<Block>
类型的Block
也是如此。
- 为什么我需要在以下示例中在 block_cache.h 之前包含 block_cache_key.h 和 block.h
- 什么 clang-format 相当于 rustfmt 的 indent_style=Block?
- 如何定义此"if block"中其他无效输入的值,以便在c ++中将字符串转换为对象?
- de if-Block 是什么意思
- Eigen::MatrixXd.block assignment using a std::vector
- base64 decode with openssl BIO block by block
- CACHE在C 中遗忘的矩阵换位实现
- "Do not change a loop variable inside a for loop block"的意义是什么?
- Metis - Block output
- 保留所有处理器资源、Core和Cache
- 将 .block() 与复矩阵 eigen lib 一起使用
- 使用block()在分配中使用block()缩小矩阵
- 测试环形缓冲区实现的"cache not flushed to main memory"
- 如何运行由 Code::Block 创建的控制台应用程序
- 如何从特征矩阵中获取不连续的数据"block"?
- Visual Studio C++ "Automatically format completed block on }"
- 带有 MSG_PEEK 的 recv() 显示完整消息,但正常返回'would block'
- 异常从具有函数 try-block 的构造函数中引发两次
- 非局部 lambda 和捕获变量 - "block scope"是什么意思
- Do atoi() 和 atof() cache??调用的次数越多,它们似乎执行得越快