Как создать кортеж ссылок на const?
Скажем, есть две функции:
void ff( const std::tuple<const int&> ) { }
template < typename TT >
void gg( const std::tuple<const TT&> ) { }
и вызывает следующие функции:
int xx = 0;
ff( std::tie( xx ) ); // passes
gg( std::tie( xx ) ); // FAILS !!
GCC 4.7.2 не может скомпилировать последнюю строку и сообщает об ошибке, например:
note: template argument deduction/substitution failed:
note: types ‘const TT’ and ‘int’ have incompatible cv-qualifiers
note: ‘std::tuple<int&>’ is not derived from ‘std::tuple<const TT&>’
Первый вопрос: если это соответствует стандарту С++ 11, а если нет, то почему?
Кроме того, для преодоления этой проблемы необходимо передать кортеж ссылок const на gg
вместо передачи набора неконстантных ссылок (что делает std::tie
). Это можно сделать:
gg( std::tie( std::cref(x) ) );
однако дополнительный вызов std::cref
является довольно утомительным, поэтому было бы здорово иметь что-то вроде ctie
, которое создавало бы кортеж ссылок const.
Второй вопрос: нужно ли писать ctie
вручную, и если да, то это лучший способ сделать это?
template < typename... T >
std::tuple<const T&...> ctie( const T&... args )
{
return std::tie( args... );
}
Ответы
Ответ 1
Первый вопрос: если это соответствует стандарту С++ 11, а если нет, то почему?
Это ожидаемое поведение. Во втором случае вывод аргумента шаблона невозможен, потому что нет T
, так что tuple<const T&>
становится tuple<int&>
.
В первом случае это работает, потому что tuple<int&>
неявно конвертируется в tuple<const int&>
. Это пользовательское преобразование и, как таковое, не учитывается при выводе аргумента шаблона.
Ваши вопросы немного пахнут проблемой X/Y. Рассмотрите возможность публикации реального вопроса, который заставил вас искать решение, включающее эту комбинацию шаблонов функций/кортежей.
Ваш шаблон функции ctie
выглядит нормально. Но имейте в виду, что такие вещи, как
auto t = ctie(5);
будет в основном создавать оборванную ссылку. Таким образом, вы можете ограничить ctie
только lvalues.