我正在考虑使大型代码库shellcheck的所有bash脚本兼容,但任务是压倒性的,因为过多的开发人员历来忽略所有shell脚本的第一个规则:始终使用引号.
如果有一个工具可以至少修复报价,那将会很有帮助.然后,我可以手动修复其余部分.我正则表达式并没有削减它,因为只有变量不是已经在一个字符串必须加引号.
样本输入:
echo "Removing $a ${b} $(c $(c)) `d $d` ${10} $@ now"
rm -rf $a ${b} $(c $(c)) `d $d` ${10} $@
Run Code Online (Sandbox Code Playgroud)
样本输出:
echo "Removing $a $b $(c "$(c)") `d "$d"` ${10} $@ now"
rm -rf "$a" "$b" "$(c "$(c)")" "$(d "$d")" "${10}" "$@"
Run Code Online (Sandbox Code Playgroud)
它不需要修复上述所有内容,它甚至不必完美无瑕(虽然这将是非常好的),但它必须是正确的,而不是没有用.
这是我天真的正则表达式没有削减它:
s:([^"])\$\{([_A-Za-z0-9]+)\}([^"]|$):\1"\$\2"\3:g
Run Code Online (Sandbox Code Playgroud)
它将$ {identifier}转换为"$ identifier",除非紧接在引号前面或后面,但无法检测到我们是否在字符串中更深.
如何就地构造一个可选的聚合?看来我只能构建一个可选的单一事物,而不能构建一个可选的事物集合。
#include <optional>
#include <iostream>
struct Unmovable
{
Unmovable(const Unmovable&) = delete;
Unmovable(Unmovable&&) = delete;
Unmovable& operator=(const Unmovable&) = delete;
Unmovable& operator=(Unmovable&&) = delete;
explicit Unmovable(const char* msg) {
std::cout << msg << '\n';
}
};
struct Things
{
Unmovable one;
Unmovable two;
};
int main(int argc, char* argv[]) {
const bool y = argc > 1 && argv[1][0] == 'y';
std::optional<Unmovable> optionalThing = y
? std::optional<Unmovable>{"works"}
: std::nullopt;
std::optional<Things> optionalThings = y
? std::optional<Things>{
#if ATTEMPT == 1
"jadda", …
Run Code Online (Sandbox Code Playgroud) 我已经围绕长寿命向量的共同主题编写了无数的软件模块,有时(在未指定的频率下)必须更新其内容.
惯用法实施:
void LongLived::reconfigure(const InputT& whatever_input)
{
m_vector.clear();
m_vector.reserve(whatever_input.size());
populate(m_vector, whatever_input);
}
Run Code Online (Sandbox Code Playgroud)
请注意,惯用实现永远不会减少其内部缓冲区的容量.如果这不好怎么办?只是用shrink_to_fit()
,我想:
void LongLived::reconfigure(const InputT& whatever_input)
{
m_vector.clear();
m_vector.reserve(whatever_input.size());
m_vector.shrink_to_fit(whatever_input.size()); // ? Here
populate(m_vector, whatever_input);
}
Run Code Online (Sandbox Code Playgroud)
哦,那将是多么美好......但令我惊讶的是,它没有编译,因为shrink_to_fit()
不需要一个数字!
shrink_to_fit()
应该使用的方式显然是先填充向量.然后,你调用shrink_to_fit()
,这将从事后的向量中的元素数量中获得容量需求,但如果我事先已经告诉它,那显然是次优的,因为现在,所有内容都必须被移动.
目标:我想vector_reserve_or_shrink()
在这种情况下使用一个函数:
void LongLived::reconfigure(const InputT& whatever_input)
{
m_vector.clear();
vector_reserve_or_shrink(m_vector, whatever_input.size()); // ? Implement this!
populate(m_vector, whatever_input);
}
Run Code Online (Sandbox Code Playgroud)
我实际上并不痴迷于从矢量中删除每个未使用的字节.更确切地说,我很乐意将其留给某些实现定义,例如shrink_to_fit()
,可能知道分配器的怪癖,并可能选择什么都不做.通过这种方式,人们不会冒险进行抽象反转,从而否定任何较低级别的优化.例如,假设分配器的粒度是16:那么,当你要求一个时,矢量实现可能会免费给你15个字节,据我所知,这对于尝试回馈只会适得其反.
我的尝试:
Animal <|-- Cat
Animal <|-- Dog
Run Code Online (Sandbox Code Playgroud)
结果:
??????????
? Animal ?
??????????
? ?
? ?
??????????????
? Cat ?? Dog ?
??????????????
Run Code Online (Sandbox Code Playgroud)
这不是类图的样子。
我想要的是:
??????????
? Animal ?
??????????
?
????????
??????????????
? Cat ?? Dog ?
??????????????
Run Code Online (Sandbox Code Playgroud)
按照建议,我在 PlantUML 论坛上问这是否可行。
如何在构造函数(堆栈中)中存储初始化列表所需的临时状态?
例如,实现此构造函数...
// configabstraction.h
#include <istream>
class ConfigAbstraction
{
public:
ConfigAbstraction(std::istream& input);
private:
int m_x;
int m_y;
int m_z;
};
Run Code Online (Sandbox Code Playgroud)
...使用像这样的有状态助手类?
// mysillyparserdontworry.h
#include <json/reader.h> //jsoncpp
class MySillyParserDontWorry
{
public:
MySillyParserDontWorry(std::istream& input) { input >> m_parseTree; }
int intByName(const char* name) const { return m_parseTree[name].asInt(); }
private:
Json::Value m_parseTree;
};
Run Code Online (Sandbox Code Playgroud)
我的尝试:
// configabstraction.cpp
ConfigAbstraction::ConfigAbstraction(std::istream& input)
: local_parserState(input) // init local variable first: Not possible!
, m_a(local_parserState.intByName("a"))
, m_b(local_parserState.intByName("b"))
, m_c(local_parserState.intByName("c"))
{
MySillyParserDontWorry local_parserState; // ...because it is local
}
Run Code Online (Sandbox Code Playgroud)
什么是C++的人为限制!
为什么placement new 依赖于#include <iostream>
?
听起来很荒谬?好吧,此代码仅在注释 include 时才编译:
// #include <iostream>
struct Alignas { void* ptr; };
alignas(Alignas) static char storage[sizeof(Alignas)];
int main() { new(storage) Alignas; }
Run Code Online (Sandbox Code Playgroud)
Gcc 错误(与 Clang 相同):
alignas.cpp:7:27: error: no matching function for call to ‘operator new(sizetype, char [8])’
7 | int main() { new(storage) Alignas; }
| ^~~~~~~
<built-in>: note: candidate: ‘void* operator new(long unsigned int)’
<built-in>: note: candidate expects 1 argument, 2 provided
<built-in>: note: candidate: ‘void* operator new(long unsigned int, std::align_val_t)’
<built-in>: …
Run Code Online (Sandbox Code Playgroud)