Я нашел способ использовать дополнительную ссылку в стандарте C ++ 11.
Считаете ли вы, что этот метод является надежным и поведение хорошо определено в соответствии со стандартом C ++?
// Optional reference using C++11
// V. Reverdy - 2013
#include <iostream>
#include <type_traits>
template <class T = int, class = typename std::enable_if<std::is_same<typename std::decay<T>::type, int>::value>::type>
void f(T&& n = T())
{
std::cout<<"--------"<<std::endl;
std::cout<<"is const = "<<std::is_const<T>::value<<std::endl;
std::cout<<"is reference = "<<std::is_reference<T>::value<<std::endl;
std::cout<<"is lvalue reference = "<<std::is_lvalue_reference<T>::value<<std::endl;
std::cout<<"is rvalue reference = "<<std::is_rvalue_reference<T>::value<<std::endl;
std::cout<<"--------"<<std::endl;
n *= 2;
}
int main(int argc, char* argv[])
{
int n = 42;
std::cout<<"n = "<<n<<std::endl;
f();
std::cout<<"n = "<<n<<std::endl;
f(n);
std::cout<<"n = "<<n<<std::endl;
return 0;
}
Результат:
n = 42
--------
is const = 0
is reference = 0
is lvalue reference = 0
is rvalue reference = 0
--------
n = 42
--------
is const = 0
is reference = 1
is lvalue reference = 1
is rvalue reference = 0
--------
n = 84
Кажется, он работает на всех компиляторах, доступных в liveworkspace: LWS
Wat.
Во-первых, то, что вы «достигли», может быть гораздо проще, скажем, путем перегрузки. А во-вторых, это не то же самое, что необязательная ссылка совсем. Необязательная ссылка — это значение, которое может содержать или не содержать ссылку. во время выполнения. Поведение четко определено, но это не желательно и не является дополнительной ссылкой. Привязка ссылок к временным файлам в качестве аргументов по умолчанию хороша в некоторых ситуациях, но это миллиард миль от необязательной ссылки.
Это четко определено, да, потому чтоуниверсальные ссылки«(имейте в виду, что это нестандартный термин) может преобразовываться в ссылки на rvalue и, следовательно, связываться с временными файлами, но вы не создаете»необязательная ссылка».
Ссылки всегда должны быть инициализированы и всегда должны быть связаны с объектом, они не могут быть «связаны или не связаны» (что является моим интуитивным пониманием того, что вы подразумеваете под «»необязательная ссылка«).
Здесь вы просто привязываете эту ссылку к временному. То, что вы сделали, эквивалентно следующему:
template<typename T> void f(T&& t) { ... }
void f() { f(int()); }
Если вы хотели сказать, что теперь вы можете создать функцию, которая принимает ссылку и может быть вызвана без предоставления какого-либо аргумента — что является ИМО более правильным способом ее выражения — тогда это правда, но я бы не стал это рассматривать сенсационное открытие.
Даже в C ++ 03 вы могли бы сделать что-то подобное, хотя для ссылок на const
только:
template<typename T>
void f(T const& = T()) { ... }
С C ++ 11 введены неconst
Ссылки, которые могут связываться с временными (rvalue ссылки), следует естественное обобщение, которое использует ваша техника.