3

When inheriting a constructor template, GCC (6.2.0 via MinGW-w64, 6.3 via Ideone.com) seems to ignore access modifiers.

#include <iostream>

class Base
{
protected:
    template<typename ...Args>
    Base(Args ...args)
    {
        std::cout << "variadic ctor" << std::endl;
    }

    template<typename T>
    Base(T t)
    {
        std::cout << "template ctor" << std::endl;
    }

    Base(char const *s)
    {
        std::cout << s << std::endl;
    }
};

class Derived : public Base
{
protected:
    using Base::Base;
};

int main(int, char**) noexcept
{
    //Base bv{ 0, 1 }; // error: 'Base::Base(Args ...) [with Args = {int, int}]' is protected within this context
    //Base bt{ 0 }; // error: 'Base::Base(T) [with T = int]' is protected within this context
    //Base bs{ "base" }; // error: 'Base::Base(const char*)' is protected within this context
    Derived dv{ 0, 1 };
    Derived dt{ 0 };
    //Derived ds{ "derived" }; // error: 'Derived::Derived(const char*)' is protected within this context
    return 0;
}

None of these should be constructible, but the Derived class is still constructible through the templated constructors. As shown by the char const constructor, only the non-template constructor inherits proper access modifiers.

Live Demo

This is incorrect behavior, isn't it?

EDIT: This answer provides the following related citation when using X::X;:

A constructor so declared has the same access as the corresponding constructor in X.

From 12.9/4, "Inheriting constructors".

Community
  • 1
  • 1
monkey0506
  • 2,489
  • 1
  • 21
  • 27
  • 1
    I can't see how this would be correct behavior. I find nothing in the standard might explain this, and a few things that support the concept that the usual accessibility rules apply, here. – Sam Varshavchik Mar 18 '17 at 01:24
  • Thanks, @SamVarshavchik. I added a link to another answer which says much the same, and while it doesn't explicitly mention the case of templates, they shouldn't (apparently) be an exception. – monkey0506 Mar 18 '17 at 01:35
  • That was one of the things I looked at. That seems to suggest that it doesn't matter whether `using` appears in a private/protected/public section, the inherited constructor inherits the accessibility also -- which I didn't expect, but that still doesn't explain this... – Sam Varshavchik Mar 18 '17 at 01:41
  • 1
    There's a similar example in [namespace.udecl]/18 of N4618, however the standard is sufficiently unclear that I don't know whether the constructor is meant to be accessible or not. The text is " 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" , However it doesn't say what context the access check is performed in. In context of `B`, the `A` constructors are indeed accessible to construct an `A`. – M.M Mar 18 '17 at 02:17
  • clang++3.8 does not accept this code, neither does icc. – Volodymyr Boiko Mar 18 '17 at 12:35
  • @M.M That's the post-P0136 rule. I don't see ambiguity there; it's the same context as the original call: you can write `Derived d(1);` iff you can write `Base b(1);`. See P0136R0 for additional examples. – T.C. Mar 18 '17 at 18:26
  • This seems wrong. Did you file a bug, or find an already reported one? – underscore_d May 25 '17 at 18:11

0 Answers0