7

The using declaration for the base constructor is private, but the class can still be constructed. Why?

Accessibility works differently for the operator[]'s using declaration which must be public.

#include <vector>

template<typename T>
class Vec : std::vector<T>
{
private:
    using std::vector<T>::vector;       // Works, even if private. Why?
public:
    using std::vector<T>::operator[];   // must be public
};

int main(){
    Vec<int> vec = {2, 2};
    auto test = vec[1];
}

What if I wanted the constructor to be private? Could it be done with a using declaration?

wally
  • 10,717
  • 5
  • 39
  • 72

2 Answers2

7

Using-declarations for base class constructors keep the same accessibility as the base class, regardless of the accessibility of the base class. From [namespace.udecl]:

A synonym created by a using-declaration has the usual accessibility for a member-declaration. A using-declarator that names a constructor does not create a synonym; instead, the additional constructors are accessible if they would be accessible when used to construct an object of the corresponding base class, and the accessibility of the using-declaration is ignored

emphasis added

In plain English, from cppreference:

It has the same access as the corresponding base constructor.

If you want the "inherited" constructors to be private, you have to manually specify the constructors. You cannot do this with a using-declaration.

Justin
  • 24,288
  • 12
  • 92
  • 142
  • Alright but this implies that access to base constructor taking initializer list is `public`. Note that base class access in this example is actually `private`. – user7860670 May 03 '18 at 21:40
  • 1
    It will worth adding the first line of that paragraph from the standard. It explains why `using std::vector::operator[];` needs to be in `public` section. – R Sahu May 03 '18 at 21:45
  • 2
    The question was actually about keeping inherited constructor private. It seems that with this fancy rule it would be impossible to achieve this with just `using` declaration. Or alter access in general. – user7860670 May 03 '18 at 21:47
  • 2
    *"the additional constructors are accessible if they would be accessible when used to construct an object of the corresponding base class"* shouldn't they be inaccessible because the entire base class is inaccessible on the first place? I seems that this part is actually interpreted "regardless of the access specifier used for inheritance". – user7860670 May 03 '18 at 21:52
3

using reference states that an inherited constructor

has the same access as the corresponding base constructor.

It further gives some hint on the rationale behind this:

It is constexpr if the user-defined constructor would have satisfied constexpr constructor requirements. It is deleted if the corresponding base constructor is deleted or if a defaulted default constructor would be deleted

Apparently, you cannot explicitly constexpr or delete an inherited constructor, so those characteristics are simply inherited. Same goes for access levels.

bipll
  • 11,747
  • 1
  • 18
  • 32