Say there are two functions:
void ff( const std::tuple<const int&> ) { }
template < typename TT >
void gg( const std::tuple<const TT&> ) { }
and calls to these functions:
int xx = 0;
ff( std::tie( xx ) ); // passes
gg( std::tie( xx ) ); // FAILS !!
GCC 4.7.2 fails to compile the last line and reports an error note like:
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&>’
The first question is if this fits with the C++11 standard, and if it doesn't, then why?
Furthermore, to overcome this issue one needs to pass a tuple of const references to gg
instead of passing a tuple of non-const references (which std::tie
makes). This can be done by:
gg( std::tie( std::cref(x) ) );
however, an extra call to std::cref
is kind of tedious, so it would be great to have something like ctie
which would make a tuple of const references.
The second question is if there is a need to write ctie
manually, and if yes, then is this the best way to do it?
template < typename... T >
std::tuple<const T&...> ctie( const T&... args )
{
return std::tie( args... );
}
return std::move(<Expression>);
is an anti-pattern - it's universally better to simplyreturn <Expression>;
In this particular case,std::tie(args...)
is already an rvalue anyway. See this answer for discussion. – Adelinaadelind