>> I am unaware of a way to sfinae on mentioning a specialization. I know how
>> to sfinae on expressions that use the type. As in
>> http://cplusplus.github.io/LWG/lwg-active.html#2543
#include <climits>
#include <cstdint>
#include <cstdio>
#include <cstring>
#include <type_traits>
namespace meow //std
{
template <int B>
struct _int_t_helper;
template <> struct _int_t_helper<8> { typedef std::int8_t type; };
template <> struct _int_t_helper<16> { typedef std::int16_t type; };
template <> struct _int_t_helper<32> { typedef std::int32_t type; };
template <> struct _int_t_helper<64> { typedef std::int64_t type; };
template <int B>
using int_t = typename _int_t_helper<B>::type;
}
char (&Function(...))[99];
template <int S>
meow::int_t<S * CHAR_BIT> Function(unsigned char (&)[S]);
int main()
{
unsigned char buffer1[1];
unsigned char buffer2[2];
unsigned char buffer3[3];
unsigned char buffer4[4];
std::printf("%zu %zu %zu %zu\n", sizeof(Function(buffer1)), sizeof(Function(buffer2)),
sizeof(Function(buffer3)), sizeof(Function(buffer4)));
}
-?- For any type T that is not of integral or enumeration type, or for which neither the library nor the user provides an explicit or partial specialization of the class template hash, the specialization of hash<T> has the following properties:
[Note: this means that the specialization of hash exists, but any attempts to use it as a Hash will be ill-formed. — end note]
On Tuesday, September 6, 2016 at 1:51:52 PM UTC-7, Ville Voutilainen wrote:On 6 September 2016 at 23:42, Myriachan <myri...@gmail.com> wrote:
> I mean substitution failure for SFINAE along these lines, where the output
> is "1 2 99 4":
Well, I can give you what you want either with concepts or with a
suitably-enable_if-constrained alias template.
The wording "using the specialization is ill-formed" gives you SFINAE,
since I didn't add ", no diagnostic required".
Does this work?
(int_t, uint_t)
int_t<B> is an alias for intB_t if the implementation provides the type intB_t; otherwise, using the specialization int_t<B> is ill-formed.
Does this need a "Note:" to make explicit the intent that the ill-formed cases are meant to cause substitution failure for SFINAE, rather than "hard" errors?
From: Arthur O'Dwyer Sent: Tuesday, September 6, 2016 7:16 PM |
To: ISO C++ Standard - Future Proposals Reply To: std-pr...@isocpp.org Subject: Re: [std-proposals] What header should int_t go to? |
On Tuesday, September 6, 2016 at 1:51:52 PM UTC-7, Ville Voutilainen wrote:On 6 September 2016 at 23:42, Myriachan <myri...@gmail.com> wrote:
> I mean substitution failure for SFINAE along these lines, where the output
> is "1 2 99 4":
Well, I can give you what you want either with concepts or with a
suitably-enable_if-constrained alias template.
The wording "using the specialization is ill-formed" gives you SFINAE,
since I didn't add ", no diagnostic required".
Does this work?
(int_t, uint_t)
int_t<B> is an alias for intB_t if the implementation provides the type intB_t; otherwise, using the specialization int_t<B> is ill-formed.
(int_least_t, uint_least_t, int_fast_t, uint_fast_t)
int_least_t<B> is an alias for int_leastN_t, where N is the smallest integer greater than or equal to B such that the implementation provides int_leastN_t. If B is less than 1, or if B is greater than the largest such integer N, using the specialization int_least_t<B> is ill-formed.
Would Standardese repeat those lines for all four variants, or somehow reword it to apply to all four?
Does this need a "Note:" to make explicit the intent that the ill-formed cases are meant to cause substitution failure for SFINAE, rather than "hard" errors?
Melissa
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/2323f8aa-64f4-4115-8054-3e9937932916%40isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAOfiQqnSNEjDhXw7jcduNMEWzU5maJk8%2BK__XbD6qPy494ZgMg%40mail.gmail.com.
Reply To: std-pr...@isocpp.org Subject: Re: [std-proposals] What header should int_t go to? |
I think this is overly restrictive; if an implementation can provide int_t<N> for other values of N, I don't see why that should be disallowed.
On Tuesday, September 6, 2016 at 6:45:44 PM UTC-7, Richard Smith wrote:I think this is overly restrictive; if an implementation can provide int_t<N> for other values of N, I don't see why that should be disallowed.
Yeah, you're right. I would say that whatever types exist in cstdint ought to exist in the templates, though. (C++ doesn't state that an implementation can have these types in <cstdint> for numbers except 8, 16, 32 and 64, but C does state this. I think that this should be corrected, with an implementation being allowed to define a std::int28_t.)
I did come up with another issue, though. This rule is in [temp.res]/8:
"If no valid specialization can be generated for a template, and that template is not instantiated, the template is ill-formed, no diagnostic required."
int_t<B> as I wanted to define it would potentially violate this rule. If an implementation has no types that meet the requirements of int_t<B> for any B, then an implementation would need an int_t somewhat like this:
template <int B> struct _undefined_struct;
template <int B> using int_t = typename _undefined_struct<B>::_type;
But then no valid template instantiation would exist, violating the rule, even though it's actually a desirable outcome here (SFINAE could detect that int_t<B> doesn't exist for some B).
On Tuesday, September 6, 2016 at 6:45:44 PM UTC-7, Richard Smith wrote:I think this is overly restrictive; if an implementation can provide int_t<N> for other values of N, I don't see why that should be disallowed.
Yeah, you're right. I would say that whatever types exist in cstdint ought to exist in the templates, though. (C++ doesn't state that an implementation can have these types in <cstdint> for numbers except 8, 16, 32 and 64, but C does state this. I think that this should be corrected, with an implementation being allowed to define a std::int28_t.)
I did come up with another issue, though. This rule is in [temp.res]/8:
"If no valid specialization can be generated for a template, and that template is not instantiated, the template is ill-formed, no diagnostic required."
int_t<B> as I wanted to define it would potentially violate this rule. If an implementation has no types that meet the requirements of int_t<B> for any B, then an implementation would need an int_t somewhat like this:
template <int B> struct _undefined_struct;
template <int B> using int_t = typename _undefined_struct<B>::_type;
In it, the equivalent to std::int_t<BITS> would be set_width_t<int, BITS>. This type could be user-specialized for non-built-in integral types.
Note that that name is certainly going to change (perhaps make_int_t or make_bitwidth_t) and that I suggest fast and least variants.
--
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CACGiwhE1np8gzhyE-%2B9kXLJdoRUE9Smo2Jh9CYq-KWyz9ZYTQA%40mail.gmail.com.
The appeal of `make_` is that there is already `make_signed` which is closely related: it takes one type and changes a single attribute about it, yielding another type.The `_t` variants are a convenience types; they're another matter altogether. For example, `make_signed_t<T>` which is shorthand for `typename make_signed<T>::type`.
As an aside, I wonder, will the stdlib ever start putting its type helper structs in detail namespaces (as they are effectively just boilerplate) and only expose the related using alias - as I do with some of my template stuff - or is there a reason to keep both available as part of the interface?