2

I have something like this (C++11)

std::tuple<const MyType&, bool> func()
{
   return std::make_tuple(some_internal_reference, true);
}

the problem is that in the caller I cannot declare:

const MyType& obj; // this does not compile of course
bool b;

std::tie(obj, b) = func();

An idea is to return the boolean as an output param and drop the tuple, but is there a better solution?

Enlico
  • 23,259
  • 6
  • 48
  • 102
Taw
  • 479
  • 3
  • 15
  • 1
    What about replacing reference with pointer? – Karen Baghdasaryan Aug 26 '21 at 11:11
  • A non const reference? The idea of pass a cont reference (according to Scott Mayers) - don't copy a object, and don't delete (call to destructor) original object. In any case `const MyType& obj;` means reference is non modifiable, so what the propose of this ? Another option use move semantic i.e. `std::make_tuple( std::move(some_internal_reference), true);` and i think this is what are you looking for. – Victor Gubin Aug 26 '21 at 11:14
  • 1
    @VictorGubin The issue here is the reference, not the `const`. And `std::move` wouldn't solve anything either. – interjay Aug 26 '21 at 11:16
  • @interjay tuple is a struct, what the propose to hold a const reference inside struct ? Looks like tuple need to temporary propose, i.e. some kind of self made compile time reflection. In this case it can be solved by move semantic without any references at all. – Victor Gubin Aug 26 '21 at 11:18
  • 3
    Use `std::get`, it returns a reference. `auto tup = func(); const MyType& obj = std::get<0>(tup);`. – Vladimir Talybin Aug 26 '21 at 11:23
  • 1
    `std::make_tuple` performs a decay copy of its arguments. It doesn't deduce references for members. Are you sure this is the reduced problem? – StoryTeller - Unslander Monica Aug 26 '21 at 11:50
  • @StoryTeller-UnslanderMonica yep, thank you. does it make a copy even if I use `std::tuple(std::ref(m_obj),...)`? `m_obj` is a member variable – Taw Aug 26 '21 at 12:23
  • 1
    @Taw - You mean `std::make_tuple(std::ref(...)...)`? It will help *you* get help if your code samples are precise. A [mre] goes a long way towards getting help. And yes, `std::ref` is one way to make it work. It's the standard way to alter the behavior of `make_tuple`. – StoryTeller - Unslander Monica Aug 26 '21 at 12:28
  • @Taw, what's the problem with Vladimir's proposal? You don't pay for any copy there. The only drawback is a name, `tup`, which wouldn't exist in the C++17's structured binding approach. – Enlico Aug 26 '21 at 12:31
  • @Enlico I agree that Vladimir's proposal is the best suited to my needs until now, I will probably use it. – Taw Aug 26 '21 at 12:34
  • @StoryTeller-UnslanderMonica thank you, usually I use compiler explorer to create small examples, I should have done it now also, thanks for your help – Taw Aug 26 '21 at 12:44
  • @VladimirTalybin please mark your post as an answer, I will approve it as accepted. Thanks everybody for your help. – Taw Aug 26 '21 at 12:45

1 Answers1

1

Use std::get. It returns reference to stored element.

#include <iostream>
#include <tuple>

using MyType = int;
MyType some_internal_reference = 42;

std::tuple<const MyType&, bool> func()
{
    return { some_internal_reference, true };
}

int main()
{   
    auto ret = func();
    const MyType& obj = std::get<0>(ret);
    
    std::cout << "before change: " << obj << '\n';
    
    some_internal_reference = 7;

    std::cout << "after change: " << obj << '\n';
}

It prints

before change: 42
after change: 7

Note, as per @StoryTeller-UnslanderMonica comment, don't use std::make_tuple in this case. It stores a decay (naked type) copy.