Skip to content

Latest commit

 

History

History
95 lines (86 loc) · 18.2 KB

Lecture 09.md

File metadata and controls

95 lines (86 loc) · 18.2 KB


Еще о фичах

Decltype

vector<int> g(int float);
char g(string&, int);
template <typename ... T>
T* g(T, T*);

template <typename ... T> ??? f(T&& ... args) { return g(std::forward<T>(args) ...) }

Что ставить на место ???

С простыми типами можно:

typename std::common_type<U, V>::type max(U const& u, V const& v) {
	return u < v ? v : u;
}

Есть встроенная возможность:

template <typename ... T>
decltype(g(std::forward<T>(args) ...)) f(T&& ... args) {
	return g(std::forward<T>(args) ...);
}

Но вот проблема, args используется до объявления
В c++11 появилась возможность указать тип возвращаемого значения после объявления функции (trailing return type)

template <typename ... T>
auto f(T&& ... args) -> decltype(g(std::forward<T>(args) ...)) {
	return g(std::forward<T>(args) ...);
}

А что если мы не хотим использовать args?

template <typename ... T>
auto f(T&& ... args) -> decltype(g(std::forward<T>(T()) ...)) {
	return g(std::forward<T>(args) ...);
}

Не работает из-за: 1) может отсутствовать конструктор по умолчанию, 2) args - lvalue, T() - rvalue

Выход?

tepmlate<typename T>
T& declval();

template <typename ... T> auto f(T&& ... args) -> decltype(g(std::forward<T>(declval(T)) ...)) { return g(std::forward<T>(args) ...); }

Такая штука может использоваться только в non-evaluating context

В c++14 появилась возможность делать просто

template <typename ... T>
auto f(T&& ... args) {
	return g(std::forward<T>(args) ...);
}

Хоть и компактно, но перестает работать для SFINAE

Существует 2 формы decltype

  1. decltype(var) - возвращает просто тип переменной
  2. decltype(expr)
    НЕОЖИДАННО НАМ ВРАЛИ
    Что возвращает этот decltype?
    prvalue - T, decltype(a) = int
    lvalue - T&, decltype((a)) = int&
    xvalue - T&& (rvalue находящийся на грани уничтожения)
	T f()
	T a = f(); //f() - prvalue, можем не вызывать конструктор
T<span class="token operator">&amp;&amp;</span> <span class="token function">f</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
T a <span class="token operator">=</span> <span class="token function">f</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// f() - xvalue, не можем не вызывать конструктор</span>

nullptr

Можно инициализировать нулевой указатель нулем
Но тут возникают проблемы с перегрузками по int и void*, а также с perfect forwarding по тем же параметрам
Появился nullptr, который имеет свой собственный тип nullptr_t, который может приводиться к указателю на любой тип

Указатель на member функцию

struct foo {  
    int bar(int a) {  
        return a;  
  }  
};

int (foo:: p)(int) = (&foo::bar);
foo v;
(v.
p)(5);

foo p (v->p)(10);