From: Nikolay Ivchenkov on
On 14 Apr, 15:19, Daniel Kr�gler <daniel.krueg...(a)googlemail.com>
wrote:
> Notice that the specification
> describes a context that would require public access
> in all cases.

Where exactly the specification describes the context where expression
CE is supposed to appear?

> > So, if the value of expression
> > "std::is_constructible<X, int>::value" depends on the constructor's
> > accessibility in a given context, then is_constructible is actually
> > not a part of the library, instead it shall be considered as core
> > language construct like dynamic_cast.
>
> Well, this is a stylistic question, and does not have any
> normative impact. If the library defines semantics of
> components that does not work without compiler-support,
> this is maybe odd but nothing fundamentally wrong.

A library component may be _implemented_ by the use of some specific
compiler support. But any _usage_ of a library component shall obey
the usual rules.

On 14 Apr, 15:18, Mathias Gaunard <loufo...(a)gmail.com> wrote:
> On 13 avr, 22:57, Daniel Kr�gler <daniel.krueg...(a)googlemail.com>
> wrote:
>
> > std::is_constructible
> > needs compiler-support
>
> Not necessarily.
> You could use SFINAE to check whether the expressions that defines
> is_contructible's value are well-formed.

SFINAE does not apply to violation of the access rules. See N3092 -
14.8.2/8:

"If a substitution results in an invalid type or expression, type
deduction fails. An invalid type or expression is one that would be
ill-formed if written using the substituted arguments. Access checking
is not done as part of the substitution process. Consequently, when
deduction succeeds, an access error could still result when the
function is instantiated."


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Nikolay Ivchenkov on
On 16 Apr, 23:01, Daniel Kr�gler <daniel.krueg...(a)googlemail.com>
wrote:
> I would say, that this is probably a border-case and the wording
> could (and should) be improved. I'm going to file this as an NB
> comment.

Note that publicity of _any_ member function directly invoked by the
expression CE should be checked.

#include <iostream>
#include <type_traits>

class A
{
~A() {} // private
};

class B
{
public:
B() {}
private:
B(B const &) {}
};

class C
{
operator int() { return 0; } // private
};

struct X
{
X(A) {}
X(B) {}
X(int) {}
};

int main()
{
std::cout << std::is_constructible<X, A>::value;
std::cout << std::is_constructible<X, B>::value;
std::cout << std::is_constructible<X, C>::value;
}

Note also that well-formed expression could render the program ill-
formed. In particular, the program is ill-formed if an undefined
function is used:

#include <type_traits>

struct Y
{
Y(int); // has no definition
};

int main()
{
// OK
!std::is_constructible<Y, int>::value ?
(void)Y(0) : (void)sizeof Y(0);

// renders the program ill-formed
std::is_constructible<Y, int>::value ?
(void)Y(0) : (void)sizeof Y(0);
}

So, it is very important to distinguish "ill-formed program" and "ill-
formed expression". However, there are several places in the
specification where the notion of ill-formedness applies to entire
program when it presumably should apply to a certain construct. For
example:

4.10/3:
"A prvalue of type "pointer to cv D", where D is a class type, can be
converted to a prvalue of type "pointer to cv B", where B is a base
class (Clause 10) of D. If B is an inaccessible (Clause 11) or
ambiguous (10.2) base class of D, a program that necessitates this
conversion is ill-formed."

This wording doesn't say that an expression or an initialization which
necessitates ambiguous derived-to-base pointer conversion is ill-
formed. How shall std::is_constructible handle this case?

#include <iostream>
#include <type_traits>

struct B {};

struct B1 : B {};
struct B2 : B {};

struct D : B1, B2 {};

int main()
{
std::cout << std::is_constructible<B *, D *>::value;
}

Another example:

8.5/8:
"A program that calls for default-initialization or value-
initialization of an entity of reference type is ill-formed."

What is the result of the following program?

#include <iostream>
#include <type_traits>

int main()
{
std::cout << std::is_constructible<int &>::value;
}

The same questions should be addressed to the use of SFINAE principle
that is also based on the notion of ill-formedness of a particular
constructs.


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]