#include<iostream>usingnamespacestd;classGfG{public:// Static data member
staticinti;GfG(){// Do nothing
};};// Static member inintialization
//int GfG::i = 1;
intmain(){// Prints value of i
cout<<GfG::i;}
1
2
3
/tmp/ccPusLB5.o: In function `main':
Solution.cpp:(.text.startup+0xd): undefined reference to `GfG::i`
collect2: error: ld returned 1 exit status
编译器在编译阶段为可能存在的 int GfG:: 打上引用,因为编译器假设 GfG::i 的定义会在其他地方提供,然而链接的阶段并没有找到为 GfG::i 分配空间的地方,所以抛出一个引用错误 undefined reference to GfG::i
// C++ Program to show the implementation of
// tag dispatch
#include<bits/stdc++.h>usingnamespacestd;// Creating the different tags of type empty
// struct
structt1{};structt2{};// Defining a function for type t2
voidfun(inta,t1){cout<<"Calling function of tag t"<<a<<endl;}// Defining the function with different
// implementation for type t2
voidfun(inta,t2){cout<<"Function with tag t"<<a<<endl;}intmain(){// Function calling with different tags
fun(1,t1{});fun(2,t2{});return0;}
标签调度,其实是利用函数重载的一种 c++ 技巧,可以用来处理这样一种情况:你要做出不同的操作对具有相似参数和返回值的同名函数。
#pragma once
#include<optional>#include<stdexcept>/*
* A Ref<T> represents a "borrowed"-or-"owned" reference to an object of type T.
* Whether "borrowed" or "owned", the Ref exposes a constant reference to the inner T.
* If "owned", the inner T can also be accessed by non-const reference (and mutated).
*/template<typenameT>classRef{static_assert(std::is_nothrow_move_constructible_v<T>);// Type Trait : 模板 T 是否是可移动构造的?
// _v : 获取类型特性模板类中 :: value , 在 c++17 之前 ,通过 std::is_nothrow_move_constructible<T>::value
static_assert(std::is_nothrow_move_assignable_v<T>);public:// default constructor -> owned reference (default-constructed)
Ref()requiresstd::default_initializable<T>:obj_(std::in_place){}// construct from rvalue reference -> owned reference (moved from original)
Ref(T&&obj):obj_(std::move(obj)){}// NOLINT(*-explicit-*)
// move constructor: move from original (owned or borrowed)
Ref(Ref&&other)noexcept=default;// move-assignment: move from original (owned or borrowed)
Ref&operator=(Ref&&other)noexcept=default;// borrow from const reference: borrowed reference (points to original)
staticRefborrow(constT&obj){Refret{uninitialized};ret.borrowed_obj_=&obj;returnret;}// duplicate Ref by producing borrowed reference to same object
Refborrow()const{Refret{uninitialized};ret.borrowed_obj_=obj_.has_value()?&obj_.value():borrowed_obj_;returnret;}#ifndef DISALLOW_REF_IMPLICIT_COPY
// implicit copy via copy constructor -> owned reference (copied from original)
Ref(constRef&other):obj_(other.get()){}// implicit copy via copy-assignment -> owned reference (copied from original)
Ref&operator=(constRef&other){if(this!=&other){obj_=other.get();borrowed_obj_=nullptr;}return*this;}#else
// forbid implicit copies
Ref(constRef&other)=delete;Ref&operator=(constRef&other)=delete;#endif
~Ref()=default;boolis_owned()const{returnobj_.has_value();}boolis_borrowed()const{returnnotis_owned();}// accessors
// const reference to object (owned or borrowed)
constT&get()const{returnobj_.has_value()?*obj_:*borrowed_obj_;}// mutable reference to object (owned only)
T&get_mut(){if(notobj_.has_value()){throwstd::runtime_error("attempt to mutate borrowed Ref");}return*obj_;}operatorconstT&()const{returnget();}// NOLINT(*-explicit-*)
operatorT&(){returnget_mut();}// NOLINT(*-explicit-*)
constT*operator->()const{return&get();}T*operator->(){return&get_mut();}explicitoperatorstd::string_view()constrequiresstd::is_convertible_v<T,std::string_view>{returnget();}Trelease(){if(obj_.has_value()){returnstd::move(*obj_);}#ifndef DISALLOW_REF_IMPLICIT_COPY
returnget();#else
throwstd::runtime_error("Ref::release() called on borrowed reference");#endif
}private:constT*borrowed_obj_{};std::optional<T>obj_{};structuninitialized_t{};staticconstexpruninitialized_tuninitialized{};explicitRef(uninitialized_t/*unused*/){}};template<typenameT>staticRef<T>borrow(constT&obj){returnRef<T>::borrow(obj);}
$Q \& A$
static_assert 是做什么用的?为什么这里要检查 std::is_nothrow_move_constructible_v<T> 和 std::is_nothrow_move_assignable_v<T>?如果 T 类型不满足这些条件会怎么样?