2

For example, I have a class

class A
{
public:
    template<class T, class... Args>
    void set(Args&&... args);

private:
    std::shared_ptr<Member1Type> m_member1;
    std::shared_ptr<Member2Type> m_member2; // Member types are all different.
};

And I hope I can use it as

A a;
a.set<Member1Type>(args... to construct Member1Type);

which like

make_shared<T>(args...);

My question is how to link member type to the correct member in implementing the method. Thanks!

HolyBlackCat
  • 78,603
  • 9
  • 131
  • 207
user1899020
  • 13,167
  • 21
  • 79
  • 154
  • You could provide a [pointer to data member](https://en.cppreference.com/w/cpp/language/pointer#Pointers_to_data_members) to `set` to tell it which member to set. But to do that you would need to expose the members, including their underlying type at which point there isn't really any point in trying to encapsulate it with a setter. – François Andrieux Nov 15 '18 at 15:17

3 Answers3

7

I'd populate a std::tuple<MemberType1*, MemberType2*, ...> in the ctor, so you can then use get<T*>(m_tuple) in A::set<T, Args...>

[edit] Or as StoryTeller suggested, without extra members:

private:
    std::tuple <
        std::shared_ptr<Member1Type>,
        std::shared_ptr<Member2Type>
    > m_members;

You'd now need std::get<std::shared_ptr<T>>(m_members)

MSalters
  • 173,980
  • 10
  • 155
  • 350
  • Note that this only works if each member has a different type and invalidates the compiler generated constructors and assignment operators. They would copy or assign the `tuple` which would point to the referenced instance's members instead of the assigned or constructed instance's. – François Andrieux Nov 15 '18 at 15:20
  • @StoryTeller: Ah, I see what you're getting at. My logic was that `m_member1` might be an empty shared_ptr so I couldn't use references. But you can do away with the individual members, and store the shared_ptr directly in the tuple. – MSalters Nov 15 '18 at 15:21
  • @MSalters If the raw pointer's lifetime is coupled to an existing `shared_ptr` then there is no reason to share ownership.Raw pointers are perfectly fine when they aren't owning. Edit : Though you may want a tuple that points to the `shared_ptr*` instead to allow you to assign to it. – François Andrieux Nov 15 '18 at 15:22
  • @FrançoisAndrieux: The uniqueness is implied by the need to select the member by the single argument `T` of `set`. – MSalters Nov 15 '18 at 15:22
  • I found tuple has no such get() member method. what I need turns to finding the index of the type and then call std::get(m_members) method, right? Thanks! – user1899020 Nov 15 '18 at 15:51
  • @user1899020: My bad, [it changed to a non-member](https://stackoverflow.com/questions/3313479/stdtuple-get-member-function) when it was added to the Standard. No need for an index. – MSalters Nov 15 '18 at 16:51
3

If you don't want to go the tuple approach, one way you could do this is to provide private getters for each member, overloaded on a tag type:

template <typename T> struct type_t { };
template <typename T> constexpr type_t<T> type{};

class A
{
public:
    template<class T, class... Args>
    void set(Args&&... args) {
        get(type<T>) = std::make_shared<T>(std::forward<Args>(args)...);
    }

private:
    auto& get(type_t<Member1Type>) { return m_member1; }
    auto& get(type_t<Member2Type>) { return m_member2; }

    std::shared_ptr<Member1Type> m_member1;
    std::shared_ptr<Member2Type> m_member2;
};

The auto& return avoids the need to write the type again, which already appears in the parameter list (kind of the same way you wouldn't repeat the type when writing a C++ cast).

Barry
  • 286,269
  • 29
  • 621
  • 977
-1

[enter link description here][۱

**

**strong

**

1: http://www.google play.com

enter code herequote

  1. [List item][۱]