C++ 模板显式实例化
头文件:template.hpp
#ifndef TEMPLATE_HPP
#define TEMPLATE_HPP
template <typename T>
void println(T t);
#endif
源文件:main.cpp
#include "template.hpp"
int main() {
println(9);
println(-7);
}
源文件:instantiation.cpp
头文件:template.hpp
#ifndef TEMPLATE_HPP
#define TEMPLATE_HPP
template <typename T>
void println(T t);
#endif
源文件:main.cpp
#include "template.hpp"
int main() {
println(9);
println(-7);
}
源文件:instantiation.cpp
在看 Modern CMake for C++ 的时候看到了这段代码:
void RunOutputsCorrectEquations() {
string expected {"2 + 2 = 4\n3 * 3 = 9\n"};
stringstream buffer;
// redirect cout
auto prevcoutbuf = cout.rdbuf(buffer.rdbuf());
run();
auto output = buffer.str();
// restore original buffer
cout.rdbuf(prevcoutbuf);
if (expected != output)
exit(1);
}
看起来 stdio 的 FILE 也能重定向(但是不能保存之前的关联,因而恢复到 stdout 不能跨平台):
https://stackoverflow.com/a/29154180/
// 重定向
freopen("output.txt", "a+", stdout);
// 恢复到终端输出
freopen("/dev/tty", "w", stdout); /*for gcc, ubuntu*/
// or
freopen("CON", "w", stdout); /*Mingw C++; Windows*/
cmake 的 CONFIG 生成器表达式有两种形式,一种是不接受参数、输出当前的 CONFIG 值,还有一种是判断当前的 CONFIG 是否属于几者之一。在判断 Debug 模式的时候一定要小心,因为使用 Makefile 作为生成器时,不传入 CMAKE_BUILD_TYPE 时使用的 CONFIG 为空。
target_compile_options(YourTarget PRIVATE
-Wall
$<$<CONFIG:,Debug>:-g3>
)
不过,也可以通过显式设置 CMAKE_BUILD_TYPE 来防范就是了:
if (NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Debug")
endif()
这样之后再用生成表达式创建自定义 target 打印 $<CONFIG> 的结果就是 Debug。
这篇用来记录学过但是不容易记住的写法。
CMake language
add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL] [SYSTEM])
^^^^^^^^^
e.g.
add_subdirectory(src bin)
这个操作是可以给单个文件设置不同的编译选项,而不是对 target 设置。控制的粒度就更细了。
if(MSVC AND NOT CLANG_CL)
set_source_files_properties(CompileCommands.cpp PROPERTIES COMPILE_FLAGS -wd4130) # disables C4130: logical operation on address of string constant
endif()
CMake 在 3.12 之后有 -j 选项了,无参数则表示不受限。
常用的两个 generators:
Unix Makefiles 默认使用 1 个线程,支持 -j 选项。
Ninja 也支持 -j 选项,如果不指定则使用默认线程数。可以用 ninja --help 来查看。
ninja --help 2>&1|grep -- -j
在 docker run 创建容器的时候用 --cpuset-cpus 0-3 可以限制 CPU 在 0-3 这四个核心上,实测 nproc 的结果已经改变了。
在 docker build 的时候也可以用同样的参数,比如 docker build . --cpuset-cpus 0-3,这能够被正常识别,但是 nproc 的结果没有改变,也不知道是否正常限制了。
(parentheses)
[brackets]
{braces}
<angled brackets>
\begin{document}
% Answer: [trim={left bottom right top},clip]
% Ex. 1: trim from left edge
\includegraphics[trim={5cm 0 0 0},clip]{example-image-a}
% Ex. 2: trim from right edge
\includegraphics[trim={0 0 5cm 0},clip]{example-image-a}
\end{document}
顺序是左下右上。和 css 中的 margin 的指定是相反的顺序。(css 中是上右下左。css 这个好记忆,就是初始位置在最上面,然后顺时针。)
对于整数,可以用 [[]] 和 (()) 来比较。
对于浮点数,可以用 bc,但是 bc 不是每个环境都有。
还有一种方法是 perl(如果装了 perl 但是没有装 bc):perl -e "exit(1) if not $a > $b",这样可以用返回值标志是否成功。
hash -r:用于解决在 PATH 中加入可执行文件后找不到的情况。
** 匹配多级目录(find 不能匹配双星号)
shopt -s globstar
set +o pipefail
clang-tidy -p build/ ./{src,include}/**/*.{h,hpp,cc,cpp,cu}
第一句是打开 ** 选项,第二句是忽略 pipefail(-o 和 +o 相反)不然第三句的 pipe 可能出错,第三句 2>/dev/null 是忽略错误信息。
*和**都不能直接匹配*nix上的隐藏文件,即用.开头的文件。
上述命令的功能:clang-tidy 会找到 .clang-tidy 和 build/ 下的 compile_commands.json 配置并对代码进行分析。