Скажем, есть две функции:
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&>’
Первый вопрос: соответствует ли это стандарту C ++ 11, а если нет, то почему?
Кроме того, чтобы преодолеть эту проблему, необходимо передать набор константных ссылок на gg
вместо передачи кортежа неконстантных ссылок (которые std::tie
делает). Это может быть сделано:
gg( std::tie( std::cref(x) ) );
Тем не менее, дополнительный вызов std::cref
это утомительно, так что было бы здорово иметь что-то вроде ctie
который сделал бы кортеж константных ссылок.
Второй вопрос: есть ли необходимость писать ctie
вручную, и если да, то это лучший способ сделать это?
template < typename... T >
std::tuple<const T&...> ctie( const T&... args )
{
return std::tie( args... );
}
Первый вопрос: соответствует ли это стандарту C ++ 11, а если нет, то почему?
Это ожидаемое поведение. Во втором случае вывод аргумента шаблона завершается неудачно, потому что нет T
чтобы tuple<const T&>
становится tuple<int&>
,
В первом случае это работает, потому что tuple<int&>
неявно конвертируется в tuple<const int&>
, Это пользовательское преобразование, которое не учитывается при выводе аргументов шаблона.
Ваши вопросы пахнут как проблема X / Y. Рассмотрите возможность размещения реальный Вопрос, который заставил вас искать решение, включающее такую комбинацию шаблонов функций / кортежей.
Ваш ctie
Шаблон функции выглядит нормально. Но имейте в виду, что такие вещи, как
auto t = ctie(5);
будет в основном производить висячую ссылку. Так что вы может быть хочу ограничить ctie
только для значений.
Других решений пока нет …