Search code examples
c++c++11list-initialization

std::initializer_list alternatives for noncopyable types


I know that trying to use a std::initializer_list<NonCopyable> leads to an error because the elements are copied into the temporary array represented by the initializer_list. I have also read some explanation on why it would not be alright to have rvalue references in the list, which I'm fine with.

The problem is that I would like to pass noncopyable things not in order to move from them, but only const-access them, so the argument about rvalues does not apply. What can I do to retain, if possible, the list initialization syntax and the reference semantics (no wrappers, no raw pointers)?

NonCopyable a{...}, b{...};
ListInitialized c{a, b};

I think I'm missing something extremely obvious here.

Update:

This works(*),

ListInitialized(std::initializer_list<std::reference_wrapper<NonCopyable>>) {...}

but won't accept rvalues. It would be nice if I could simply pass a list of anything that could go into const NonCopyable&.

(*) I know I wrote "no wrappers" but this affects neither the calling code nor the iteration over the list.


Solution

  • You can give ListInitialized a variadic constructor template:

    struct ListInitialized
    {
      template <class... T>
      ListInitialized(const T... &arg);
    };
    

    If you need to make sure it can only be instantiated with the correct type, consider suitable SFINAE:

    struct ListInitialized
    {
      template <
        class... T,
        class Sfinae = std::enable_if_t<std::is_same<std::decay_t<T>, NonCopyable> &&...
      >
      ListInitialized(const T... &arg);
    };