C ++ Ă© uma linguagem complexa e interessante, vocĂŞ pode melhorar quase toda a sua vida. Em algum momento, eu queria estudá-lo da seguinte forma: pegue algum aspecto da linguagem, possivelmente bastante estreito, e lide com ela da maneira mais profunda e detalhada possĂvel. Essa abordagem foi amplamente estimulada pelos notáveis ​​livros de Scott Meyers, Herb Sutter e Stephen Dewhurst. Quando uma certa quantidade de materiais se acumulou, decidi apresentar Khabrovchan a eles. EntĂŁo havia essa sĂ©rie, que eu chamei de "C ++, aprofundando". A sĂ©rie Ă© marcada como Tutorial, mas ainda nĂŁo Ă© focada em iniciantes, mas no nĂvel intermediário. O primeiro tĂłpico está sobrecarregando em C ++. O tĂłpico acabou sendo muito extenso e recebemos trĂŞs artigos. O primeiro artigo Ă© sobre sobrecarregar funções e modelos, o segundo Ă© sobrecarregar operadores e o terceiro Ă© sobrecarregar operadoresnew/delete. EntĂŁo, vamos começar a cavar.
ĂŤndice
Introdução
Em um sentido amplo, sobrecarregar Ă© a capacidade de usar simultaneamente várias funções com o mesmo nome. O compilador os distingue devido ao fato de terem um conjunto diferente de parâmetros. Nos pontos de chamada, o compilador analisa os tipos de argumentos e determina qual função especĂfica deve ser chamada. Na literatura em lĂngua russa, o termo “compartilhamento” pode Ă s vezes ser encontrado, mas parece nĂŁo ter se enraizado.
A sobrecarga é suportada por muitas linguagens de programação; consideraremos apenas o C ++ 17.
1. Disposições Gerais
1.1 Funções sobrecarregadas
( ) (overloaded), (scope) . , (=delete) .
void Foo();
char Foo(); 
void Foo(int x);
void Foo(int x) noexcept;  
void Foo(double x);
void Foo(double) = delete; 
, .
, . (decay) ,
void Foo(int x[4]);
void Foo(int x[]);
void Foo(int *x);
, .
.
, , const ( volatile),
void Foo(int x);
void Foo(const int x);
, .
1.2.
. (lookup) , (candidate functions). (template argument deduction). ( ). , . , . , , , « » (match the arguments most closely). (overload resolution). , , (ambiguous call to overloaded function). :
void Foo(float x);
void Foo(double x);
Foo("meow") , Foo(42) , , Foo(3.14f) Foo(3.14) .
(overload resolution rules) ( , ), , . .
« » : - . .
— . ( private protected). ( =delete). , . , , .
1.3.
, . . , . . , , , . () .
, . . , . , , . (hide) . , , , , , .
1.3.1.
, , . .
class X {};
X x;
x.Foo();
X::Foo(42);
X. X.
namespace N {}
N::Foo();
N, .
::Foo();
, .
«» .
, , .
( ), , .
{
    Foo();
}
. (, , . .) , ( -) .
1.3.2.
.
class B
{
public:
    void Foo(int x);
};
class D : public B
{
public:
    D();
    void Foo(double x);
};
D d;
d.Foo(42);
Foo, ? D::Foo(double), B::Foo(int) . ( D), , ( B) . D::Foo(double) . D::Foo(double) , , B::Foo(int) , . , D Foo, B B::Foo(int).
. C++ , , . . , . ( , .)
1.3.3.
C++, . ( ), :
{
    void Foo();
    void Foo(int x);
    Foo(42);
}
, , , C++ . , , , . , . ( ), ( - ) .
1.4.
using- using-. , , .
, , , , , .
1.4.1. using-
:
class B
{
public:
    void Foo(int x);
};
class D : public B
{
public:
    using B::Foo;
    void Foo(double x);
};
D d;
d.Foo(42);
Foo B, B::Foo(int).
1.4.2. using-
using- , . using- . , , using-, , . :
namespace N
{
    void Foo(int x);
}
void Foo(const char* x);
void Test()
{
    using N::Foo; 
    Foo(42);      
    Foo("meow");  
}
, Foo , using- :
namespace N
{
    void Foo(int x);
}
void Foo(const char* x);
using N::Foo;
void Test()
{
    Foo(42);      
    Foo("meow");  
}
1.4.3. using-
N.
using namespace N;
using-. N N::. N, using- (, using-, ). , , using- , .
, , , , . ( using-.)
namespace
{
    void Foo(int x);
}
void Foo(const char* x);
Foo(42);     
Foo("meow"); 
1.4.4. ,
, . :
namespace N
{
    class X {};
    void Foo(const X& x);
}
( N):
N::X x;
Foo(x);
N , , N::Foo(const X&). , (argument depended lookup, ADL), . ADL , .
2.
, .
2.1. «»
C++ . , . , , . : , , .
bool. bool int bool. . bool int.
void Foo(int x);
void Foo(bool x);
int x = 6, y = 5;
Foo(x == y); 
Foo(x = y);  
void Foo(bool x, int y);
void Foo(int x, bool y);
, :
Foo(1, 2);
, . int.
enum Qq { One = 1, Two };
void Foo(int x);
void Foo(Qq x);
Foo(One); 
Foo(42);  
, , int long .
void Foo(int x);
void Foo(long x);
Foo(42);  
Foo(42L); 
. . , , . :
void Foo(long x);
void Foo(long long x);
void Foo(float) = delete;
void Foo(double) = delete;
void Foo(long double) = delete;
2.2.
C++11 — std::nullptr_t nullptr. .
void Foo(int x);
void Foo(void* x);
Foo(0);       
Foo(nullptr); 
C++98
Foo((void*)0);
. nullptr , nullptr.
void Foo(void* x);
void Foo(std::nullptr_t);
void* x = nullptr;
Foo(x);       
Foo(nullptr); 
.
2.3.
++11 (uniform initialization) — std::intializer_list<>. , , . . .
- — {}, . , .
- , std::intializer_list<>.std::intializer_list<>, , . ,std::intializer_list<>, ( ), .
std::vector<T>, std::intializer_list<T>.
:
std::vector<int> v1(3, 1), v2{3, 1};
v1 — 3 1. v2 — 2 3 1, std::intializer_list<int>, , .
:
std::vector<const char*> u1(3, "meow"), u2{3, "meow"};
u1 u2 , 3. u2 std::intializer_list<const char*> , u1.
:
std::vector<bool> b1(3, true), b2{3, true};
b1 3 , true. b2 , std::intializer_list<bool> int bool.
[Meyers2].
2.4.
, ... , , . .
2.5.
, , . — c .
. ( , ), .
2.5.1.
. , . , . , .
, , . , . , , . [Sutter2].
C++11 (variadic templates). , , , .
2.5.2. SFINAE
, , . :
template<typename T>
void Foo(const T* x);
Foo(42);
, , , , , «» . SFINAE, Substitution Failure is not an Error ( ).
2.5.3.
, .
void Foo(int x); 
template<typename T>
void Foo(T x); 
template<>
void Foo<double>(double x); 
template<>
void Foo<const char*>(const char* x); 
template<typename T>
void Foo(const T* x); 
template<typename T>
class U {};
template<typename T>
void Foo(U<T> u); 
, :
Foo(42);       
Foo(3.14);     
Foo(42L);      
Foo("meow");   
Foo(U<int>()); 
: 1 int. .
, double int. : 1 double 1 double, .
, long int. : 1 long, .
, : 1 const char* 2 char. 2 , , 1 const char* .
, : 1 U<int> 3 int. 3 .
2.5.4.
:
void Foo(int x);     
template<typename T> 
void Foo(T x);
int, int&, const int, const int&, (long, short, unsigned int, etc.) . , (greedy). , , , . . , . — (template disabling). :
template<
    typename T,
    typename S = std::enable_if_t<!std::is_integral<T>::value>>
void Foo(T x);
SFINAE , , .
, , , :
template<typename T> 
void FooInt(T x);
template<typename T> 
void FooEx(T x);
template<typename T>
void Foo(T x)
{
    if constexpr (std::is_integral<T>::value)
    {
        FooInt(x);
    }
    else
    {
        FooEx(x);
    }
}
template<typename T>
void Foo(T x)
{
    std::is_integral<T>::value
        ? FooInt(x)
        : FooEx(x);
}
<type_traits>.
2.6. «»
«» : , , , rvalue .
. :
- lvalue — ;
- () lvalue — ;
- rvalue — lvalue, std::move();
- () rvalue — .
— .
, .
:
void Foo(T& x);
lvalue.
rvalue-:
void Foo(T&& x);
rvalue.
:
void Foo(const T& x);
void Foo(T x);
.
2.6.1. ,
:
void Foo(T& x);
void Foo(const T& x);
lvalue ( ), .
:
void Foo(T& x);
void Foo(T x);
rvalue , lvalue .
:
void Foo(const T& x);
void Foo(T x);
.
- const this.
class X
{
public:
    X();
    void Foo();       
    void Foo() const; 
    void DoSomething() const;
    void DoSomethingElse();
};
void X::DoSomething() const
{
    Foo(); 
}
void X::DoSomethingElse()
{
    Foo(); 
}
X x;
x.Foo();  
const X cx;
cx.Foo(); 
H - rvalue , rvalue. rvalue .
class X
{
public:
    X();
    void Swap(X& other) noexcept;
};
X x;
X().Swap(x); 
x.Swap(X()); 
rvalue . , . rvalue . ( , rvalue .) rvalue . , , , , . [Sutter1].
2.6.2. Rvalue
C++11 . — rvalue-. Rvalue- C++ , , rvalue-. , , «» .
:
void Foo(T&& x);
void Foo(const T& x);
rvalue ( ), .
:
void Foo(T&& x);
void Foo(T x);
lvalue , rvalue , .
:
void Foo(T&& x);
void Foo(T& x);
rvalue , lvalue , .
, — rvalue, — , , . ( .) , , , .
++11, rvalue- — -. (lvalue/rvalue) this.
class X
{
public:
    X();
    void Foo() &;  
    void Foo() &&; 
}; 
X x;
x.Foo ();  
X().Foo(); 
: rvalue- lvalue. , rvalue-, lvalue , - , std::move(), rvalue- .
2.6.3.
template<typename T>
void Foo(T&& x);
rvalue-, (universal reference). . lvalue x T&, const T&, rvalue T&&. x lvalue, - std::forward<T>(), , T&&, rvalue. (greedy), . , 2.5. (perfect forwarding) . [Meyers2].
3. ,
3.1.
C++ , - (, , , ), . (incomplete declaration), (forward declaration). . .
class X; 
class Y; 
void Foo(X* x);
void Foo(Y* y);
X* px;
Foo(px); 
X , .
3.2.
.
void Foo(int x);
void Foo(const char* x);
void (*pF)(int) = Foo; 
, . (, ) , ADL .
namespace N
{
    class X {};
    void Foo(const X& x);
}
void (*pF)(const N::X&) = Foo;    
void (*pF)(const N::X&) = N::Foo; 
using N::Foo;
void (*pF)(const N::X&) = Foo;    
.
void Foo(int x);
void Foo(const char* x);
auto pf = static_cast<void(*)(int)>(Foo); 
ADL .
, auto.
auto pf = Foo;
Foo , , pf Foo. Foo, , .
, (). std::function<>, , , std::sort(). .
- - .
class X
{
    void Foo(int a);
    void Foo(const char* a);
};
void (X::*pF)(int) = &X::Foo; 
3.3.
.
void Foo(int x);
void Foo() { Foo(0); }
void Foo(int x = 0);
, Foo(), . , .
void (*pF1)(int) = Foo; 
void (*pF0)() = Foo;    
.
, , .
3.4.
. , , , , , . («» , . 1.3). [Dewhurst]. — . , ( , - ), , . . , Visitor.
3.5.
, , — , . , . , .
, . -, std::input_iterator_tag. (typedef) — iterator_category. , -, iterator_category, , . :
void DisplayIterCat(std::input_iterator_tag tag)
{
    std::cout << "Input iterator\n";
}
template<class Iter>
void DisplayIterCat(Iter it)
{
    DisplayIterCat(typename Iter::iterator_category());
}
typename. , iterator_category Iter.
C++ , , . :
template<typename T, T val>
struct integral_constant;
T T, , . :
typedef integral_constant<bool, true> true_type;
typedef integral_constant<bool, false> false_type;
, , .
, . :
sizeof(Foo(expr))
. expr , . , Foo , Foo . .
C++17 if constexpr (), , . ( ) .
4.
— , . , .
, . , . , .
, .
— .
. Visitor
A, V
void DoDblDispatchOper(A* a, V* v);
a v , , a, v, . . , , . Visitor — [GoF].
, IAcceptor IVisitor.
class IVisitor;
class IAcceptor
{
public:
    virtual void Accept(IVisitor* visitor) = 0;
};
class A1;
class A2;
class IVisitor
{
public:
    virtual void Visit(A1* a) = 0;
    virtual void Visit(A2* a) = 0;
};
class A1 : public IAcceptor 
{
    void Accept(IVisitor* visitor) override
    {
        visitor->Visit(this);
    }
};
class A2 : public IAcceptor
{
    void Accept(IVisitor* visitor) override
    {
        visitor->Visit(this);
    }
};
class V1 : public IVisitor {};
class V2 : public IVisitor {};
IVisitor Visit() , IAcceptor. Visit() , .
void IAcceptor::Accept(IVisitor* visitor);
, :
visitor->Visit(this);
this , Visit(). Visit(), visitor.
void DoDblDispatchOper(IAcceptor* acceptor, IVisitor* visitor)
{
    acceptor->Accept(visitor);
}
Voila. .
.
- . — ( ) .
template<typename T>
void swap(T& a, T& b);
, , . . , std::swap() , , . , std::swap(), , , . , .
1. - Swap() ( ), .
class X
{
public:
    void Swap(X& other) noexcept;
};
, , C++11 noexcept.
2. , X ( , ), (-) swap() ( ):
inline void swap(X& a, X& b) noexcept { a.Swap(b); }
, ADL, std::swap() .
3. std::swap() X
namespace std
{
    template<>
    void swap<X>(X& a, X& b) noexcept { a.Swap(b); }
};
std , - . std.
, ? — . , , .
namespace N
{
    template<typename T>
    T x, y;
    swap(x, y);
, T swap(), , . std::swap() , , .
:
std::swap(x, y);
swap() std::swap() — . .
:
using std::swap;
swap(x, y);
, . std::swap(), . std::swap(). std::swap() .
, ( std)
std::swap(x, y);
swap(x, y);
[Meyers1] , .
, .
template<typename T>
class X
{
public:
    void Swap(X& other) noexcept;
};
template<typename T>
void swap(X<T>& a, X<T>& b) noexcept { a.Swap(b); }
std::swap() , std , , , , .
friend swap() :
template<typename T>
class X
{
    void Swap(X& other) noexcept;
    friend void swap(X& a, X& b) noexcept { a.Swap(b); }
};
, - Swap() .
[GoF]
., ., ., . - . .: . . — .: , 2001.
[Dewhurst]
, . C++. .: . . — .: , 2012.
[Meyers1]
, . C++. 55 .: . . — .: , 2014.
[Meyers2]
, . C++: 42 C++11 C ++14.: . . — .: «.. », 2016.
[Sutter1]
, . C++.: . . — : «.. », 2015.
[Sutter2]
Sutter, brasão de armas. Novas tarefas complexas em C ++.: Por. do inglês - M: LLC “ID. Williams, 2015.