Re: Preconditions and semantics of std::is_constructible and std::is_assignable in N3242 (C++0x draft)
On 2011-03-03 13:09, Nikolay Ivchenkov wrote:
1) Preconditions for std::is_constructible<T, Args...> are specified
as follows:
T and all types in the parameter pack Args shall be complete
types, (possibly cv-qualified) void, or arrays of unknown bound.
If my understanding is correct, X const& is complete type regardless
of whether X is complete type, so the following program is well-
defined and shall print zero:
-------------------------------------------------
#include<iostream>
#include<type_traits>
struct X;
int main()
{
std::cout<< (int)std::is_constructible<X const&, int>::value;
}
struct X
{
X(int) {}
};
-------------------------------------------------
Am I right?
I agree with your interpretation, but the intention is different. The
intention is that this *should* be a violation of pre-conditions.
Unfortunately the pre-conditions are not all correct.
2) Preconditions for std::is_assignable<T, U> are specified as
follows:
T and U shall be complete types, (possibly cv-qualified) void, or
arrays of unknown bound.
In the following example X& and X const& are complete types
regardless of whether X is complete type:
-------------------------------------------------
#include<iostream>
#include<type_traits>
struct X;
int main()
{
std::cout<< (int)std::is_assignable<X&, X const&>::value;
}
struct X {};
-------------------------------------------------
Should this program be well-defined and print zero?
Same thing here. This program is not intended to be well-defined.
The hard part is too define the pre-conditions in a way such that normal
users don't get annoyed about too strict limitations. For example there
should be no problem for code like this
#include<iostream>
#include<type_traits>
struct X;
int main()
{
std::cout<< (int)std::is_constructible<X const&, X>::value;
std::cout<< (int)std::is_constructible<X&, X&>::value;
std::cout<< (int)std::is_constructible<X&&, X>::value;
}
struct X
{
};
because all these operations are just bindings of references to possibly
cv-qualified versions of the same type.
As an approach to attack this problem we can probably discriminate the
following situations:
is_**_destructible: The current pre-conditions look ok
is_**_assignable: At least std::remove_reference<destination type>::type
needs to be a complete type. This would solve the problem in your first
example. We could be stricter and require that also
std::remove_reference<source type>::type is complete. This would fix
situations where a conversion function from source could be involved,
but it would forbid us to use std::is_assignable for situations like these:
struct Ukn;
struct S {
S& operator=(Ukn&);
};
int i = std::is_assignable<S, Ukn&>::value;
So what are the ideal pre-conditions for providing useful user-support
but not imposing?
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! ]