How to make a tuple of const references?
Asked Answered
B

1

15

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... );
}
Bo answered 13/8, 2013 at 15:35 Comment(2)
Relevant, but not a dupe.Dehorn
return std::move(<Expression>); is an anti-pattern - it's universally better to simply return <Expression>; In this particular case, std::tie(args...) is already an rvalue anyway. See this answer for discussion.Adelinaadelind
F
4

The first question is if this fits with the C++11 standard, and if it doesn't, then why?

This is expected behaviour. In the second case template argument deduction fails because there is no T so that tuple<const T&> becomes tuple<int&>.

In the first case it works because tuple<int&> is implicitly convertible to tuple<const int&>. This is a user-defined conversion and as such not considered during template argument deduction.

Your questions smells a bit like an X/Y problem. Consider posting the real question that made you look for a solution involving this kind of function template/tuple combination.

Your ctie function template looks fine. But keep in mind that things like

auto t = ctie(5);

will basically produce a dangling reference. So, you might want to restrict ctie to lvalues only.

Flashback answered 22/8, 2013 at 11:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.