From: Nikolay Ivchenkov on
According to N3092 - 11/5,
"The interpretation of a given construct is established without regard
to access control. If the interpretation established makes use of
inaccessible member names or base classes, the construct is ill-
formed".

Does it mean that the following program is ill-formed?

#include <type_traits>

class X
{
public:
X() {}
private:
X(int) {}
};

int main()
{
int bool value =
std::is_constructible<X, int>::value;
}

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

From: Nikolay Ivchenkov on
> #include <type_traits>
>
> class X
> {
> public:
> X() {}
> private:
> X(int) {}
> };
>
> int main()
> {
> int bool value =
> std::is_constructible<X, int>::value;
> }

Amendment:

#include <type_traits>

class X
{
public:
X() {}
private:
X(int) {}
};

int main()
{
const bool value =
std::is_constructible<X, int>::value;
}


--
[ 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 14 Apr, 01:57, Daniel Kru"gler <daniel.krueg...(a)googlemail.com>
wrote:
>
> "Given the following function prototype:
>
> template <class T>
> typename add_rvalue_reference<T>::type create();
>
> the predicate condition for a template specialization
> is_constructible<T, Args...> shall be satisfied if and
> only if the following expression CE would be well-formed:
>
> if sizeof...(Args) == 1, the expression:
> static_cast<T>(create<Args>()...)
> otherwise, the expression:
> T(create<Args>()...)"

The correctness of such expressions depends on context where they
appear. It would be very surprising if the same member of the same
template specialization could have different compile-time values. A
library template cannot provide such behavior because immediate
context of its use is not available within the template definition:

namespace std {
template <class T, class... Args>
struct is_constructible :
integral_constant
<
bool,
__is_constructible(T, Args...)
// we don't know immediate context here
>
{
};
}

Only core language construct could check accessibility with regard to
immediate context. 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.

I need more clear explanation - what exactly affects the value of the
expression "std::is_constructible<X, int>::value": the constructor's
publicity only or its accessibility in a context where the member
"value" of the specialization is accessed?

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

From: Mathias Gaunard on
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.



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

From: Daniel Krügler on
On 14 Apr., 13: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.

Nope, SFINAE is *not* access-tolerant. Just try

template<class T>
struct HasStaticFoo {
typedef char No;
typedef char(&Yes)[2];
template<class U, class = decltype(U::foo())>
static Yes test(void*);
template<class>
static No test(...);
static const bool value = sizeof(test<T>(0)) == sizeof(Yes);
};

struct S {
static void foo();
};

struct D {};

class X {
static void foo();
};

static_assert(HasStaticFoo<S>::value, "Ouch");
static_assert(!HasStaticFoo<D>::value, "Ouch");
static_assert(!HasStaticFoo<X>::value, "Ouch");

int main() {}

with a recent C++0x capable compiler and you will notice
that the error for X is *not* related to a violation of static_assert.

is_constructible and is_convertible are traits that *require*
compiler support, because they were intended to cope with
access restrictions. I haven't tested recent implementations
but I would expect that most of them still behave like normal
SFINAE-based realizations, which - strictly speaking - are
non-conforming, but the easiest to do for the moment.

HTH & Greetings from Bremen,

Daniel Kr�gler


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