auto:
for(auto& name : input){}
c++中name mingling较C更为复杂

创建静态链接库

gcc -fPIC -c a.c
gcc -fPIC -c b.c
gcc -shared -o libfoo.so a.o b.o


创建动态链接库

gcc -c a.c
gcc -c b.c
gcc -c main.c
ar cr libfoo.a a.o b.o
gcc main.o libfoo.a

链接:

-L [.] #添加搜索目录
-l[a] #链接liba.so
g++ -o temp ./main.so ./libb.so ./liba.so #首先查找libb,然后查找liba
alignas(64) int array[1024]; // 以64对齐内存

-l[lib] 选项需要在 cpp 文件后面(链接器从前向后处理,只从每个 lib 中提取当前需要的符号函数 见链接
-isystem [dir][dir] 指定为和系统 include,查找 include 顺序为 -I 目录,-isystem 目录,系统 include 目录

restrict关键字,告知编译器不存在指针aliasing
如:

void example2b(float * __restrict__ a, float * __restrict__ b, float * __restrict__ c) {
  for (int i = 0; i < 1024; i++) {
    a[i] = 0.0f;
    b[i] = 0.0f;
    for (int j = 0; j < 1024; j++) {
      a[i] = a[i] + c[i<em>1024 + j];
      b[i] = b[i] + c[i</em>1024 + j] * c[i*1024 + j];
    }
  }
}

告知编译器a,b,c三数组内容不重合
在cuda中,只有当指针标记为 const, restrict 时,cuda编译器才会认为数组为只读内容,并使用read-only cache对其优化

数组指针:
int p[4] : p为大小为4数组,其中每个元素为指向 int 指针。 [] 优先级高于 , 解析为 (int*) (p[4])
int (*p)[4] : p为单个指针,指向 大小为 4 的 int 数组,初始化可以直接使用 p = new int8

宏定义:
#define PRINTCLASS(ClassName) printout(#ClassName) : #ClassName传入参数转换为字符串
#define DeclareSomething(ArgumentName,i) int ArgumentName##i: ## 用于连接两个单元
#define Declare_Fun(...) typedef std::function<void(__VA_ARGS__)> iStdFunction : ... 为可变参数,用 VA_ARGS 获取

gcc -E m.cpp -o m.i : 预编译,m.i 为宏展开结果

编译与链接

-m : x86 相关选项
-march=native : 生成针对本机优化的代码
-mcmodel=large : 可以开超过 2G 的全局数组

include 文件在编译时直接使用对应文件替换 include 语句
#include "filename" 首先在源文件路径搜索目标头文件,然后搜索默认路径
#include <filename> 搜索默认路径
cpp : c pre-processor 负责头文件查找和替换
cpp -v 显示头文件查找路径
-Wl,param1,param2,... : 编译时传给ld链接器的参数

c/c++ mocking function :
-Wl,--wrap=[func]
func 进行 mock,调用 func 函数时会尝试调用 __wrap_func,使用 __read_func 调用原 func 函数

C++ 模板相关

SFINAE (substitution-failure-is-not-an-error) 原则:在模板中执行替换时解析错误不认为是错误,而是忽略该模板

#include <iostream>
using namespace std;
void f(double a){
    cout<<"in double f()"<<endl;
}
template<typename T>
void f(typename T::noexist a){
    cout<<"in T::noexist f()"<<endl;
}
int main(){
    f(1);
    f(1.0);
}

此时 f(0)f(1.0) 均调用 f(double a)

typename std::enable_if<(std::is_same<T, float>::value)>::type
当 T 为 float 时为 void type,否则解析失败

std::enable_if 定义:

template<bool B, class T = void>
struct enable_if {};

template<class T>
struct enable_if<true, T> {
    typedef T type;
};

当条件为 true 时,enable_if 包括 typedef 成员 type,等价于 T
在 C++11 中,当使用 std::enable_if 时,需要写 typename std::enable_if<...>::type
C++14 引入了 std::enable_if_t,定义为:

template<bool B, class T = void>
using enable_if_t = typename enable_if<B, T>::type;

可变模板参数

template <typename... TYPES>
void func(TYPES... vals) {
}

sizeof...(TYPES) : 参数数量
func1(vals...) : 将可变参数传入函数

折叠表达式 (Fold expressions)

从 c++17 开始。

形如 (... && args) 展开为 (((arg1 && arg2) && arg3) && ...)

integer_sequence

定义为:

template< class T, T... Ints >
class integer_sequence;

一些 helper template :
特化下标为 size_t 情况:

template< std::size_t... Ints >
using index_sequence = std::integer_sequence<std::size_t, Ints...>;

构造 0N-1 的下标序列:

template< class T, T N >
using make_integer_sequence = std::integer_sequence<T, /* a sequence 0, 1, 2, ..., N-1 */>;

template< std::size_t N >
using make_index_sequence = std::make_integer_sequence<std::size_t, N>;

构建与可变模板参数等长的序列:

template< class... T >
using index_sequence_for = std::make_index_sequence<sizeof...(T)>;

typename 用于在模板中表示一个东西是类型
decltype 用于推导表达式的类型

template <typename T>
class MyClass {
public:
    typename T::value_type member; // 'typename' specifies that T::value_type is a type

    auto getMember() -> decltype(member) {
        return member; // 'decltype' deduces the return type of the function based on 'member'
    }
};

std::same 用于在编译时比较类型

  if (std::is_same<typename DoCoul<PairStyle::COUL_FLAG>::type, CoulTag>::value) {
    printf("ERROR: DoCoul<PairStyle::COUL_FLAG>::type is CoulTag\n");
    exit(1);
  }

标签: none

添加新评论