Date: Tue, 15 Aug 2023 19:05:03 +0100
An example of using this proposed feature(and userexpr, which is another
feature yet to propose) would be:
#include <cstddef>
#include <type_traits>
namespace detailed{
template<class, class> struct types_to_params{
static_assert(false, "invalid types!");
};
template<> struct types_to_params<const char*, void>{
static consteval std::user_defined_literal_parameters value(){
return std::user_defined_literal_parameters::const_char_pointer;
}
};
template<> struct types_to_params<unsigned long long int, void>{
static consteval std::user_defined_literal_parameters value(){
return std::user_defined_literal_parameters::unsigned_long_long_int;
}
};
template<> struct types_to_params<long double, void>{
static consteval std::user_defined_literal_parameters value(){
return std::user_defined_literal_parameters::long_double;
}
};
template<> struct types_to_params<char, void>{
static consteval std::user_defined_literal_parameters value(){
return std::user_defined_literal_parameters::char_;
}
};
template<> struct types_to_params<wchar_t, void>{
static consteval std::user_defined_literal_parameters value(){
return std::user_defined_literal_parameters::wchar_t_;
}
};
template<> struct types_to_params<char8_t, void>{
static consteval std::user_defined_literal_parameters value(){
return std::user_defined_literal_parameters::char8_t_;
}
};
template<> struct types_to_params<char16_t, void>{
static consteval std::user_defined_literal_parameters value(){
return std::user_defined_literal_parameters::char16_t_;
}
};
template<> struct types_to_params<char32_t, void>{
static consteval std::user_defined_literal_parameters value(){
return std::user_defined_literal_parameters::char32_t_;
}
};
template<> struct types_to_params<const char*, std::size_t>{
static consteval std::user_defined_literal_parameters value(){
return std::user_defined_literal_parameters::const_char_pointer_with_size;
}
};
template<> struct types_to_params<const wchar_t*, std::size_t>{
static consteval std::user_defined_literal_parameters value(){
return std::user_defined_literal_parameters::const_wchar_t_pointer_with_size
;
}
};
template<> struct types_to_params<char8_t, std::size_t>{
static consteval std::user_defined_literal_parameters value(){
return std::user_defined_literal_parameters::const_char8_t_pointer_with_size
;
}
};
template<> struct types_to_params<char16_t, std::size_t>{
static consteval std::user_defined_literal_parameters value(){
return
std::user_defined_literal_parameters::const_char16_t_pointer_with_size;
}
};
template<> struct types_to_params<char32_t, std::size_t>{
static consteval std::user_defined_literal_parameters value(){
return
std::user_defined_literal_parameters::const_char32_t_pointer_with_size;
}
};
}
template<class T, class U>
inline constexpr auto types_to_params = detailed::types_to_params<T,
U>::value();
template<class R, class T, const char* suffix, bool sized = true>
requires std::user_defined_literal_r<R, types_to_params<T,
std::conditional_t<sized, std::size_t, void>>, suffix>
constexpr R instantiate_usl(T t)
{
return userexpr(t, sized, suffix);
// userexpr converts the given instance, sized or not, and suffix to its
literal representation
// in the form of an expression
}
As to why the expression-checking of constraints isn't enough because it's
tedious to write and can't handle genericity, since it must define a
concept per user-defined literal suffix and per parameter clause case, e.g,
the following code is valid under GCC and Clang trunk with -std=c++23
-Werror -pedantic -Wall -Wextra:
#include <cstddef>
void operator""_km(const char*, std::size_t);
void operator""_km(unsigned long long int); void operator""_s(const char*,
std::size_t);
template<const char*>
concept user_defined_const_char_km_literal = requires{
"a"_km;
};
template<unsigned long long int>
concept user_defined_unsigned_long_long_int_km_literal = requires{
42_km;
};
template<const char*>
concept user_defined_const_char_s_literal = requires{
"a"_s;
};
El mar, 15 ago 2023 a las 17:25, Jens Maurer (<jens.maurer_at_[hidden]>)
escribió:
> Hi,
>
> Could you give a few examples how to use this facility,
> and why the usual expression-checking machinery of
> concepts isn't enough?
>
> Jens
>
>
> On 15/08/2023 17.56, veronica alphonso via Std-Proposals wrote:
> > I would like to add a feature to the concepts(or type_traits if it's a
> better fit) library, which determines whether a user-defined literal is
> defined in the actual TU given the types of the param-list and the suffix
> for it, like:
> >
> > namespace std {
> > enum class user_defined_literal_parameters : uint8_t{
> > const_char_pointer = 0u,
> > unsigned_long_long_int = 1u,
> > long_double = 2u,
> > char_ = 3u,
> > wchar_t_ = 4u,
> > char8_t_ = 5u,
> > char16_t_ = 6u,
> > char32_t_ = 7u,
> > const_char_pointer_with_size = 8u,
> > const_wchar_t_pointer_with_size = 9u,
> > const_char8_t_pointer_with_size = 10u,
> > const_char16_t_pointer_with_size = 11u,
> > const_char32_t_pointer_with_size = 12u
> > };
> >
> > template<user_defined_literal_parameters param, const char* suffix>
> > concept user_defined_literal = /* to determine... */;
> >
> > template<class R, user_defined_literal_parameters param, const char*
> suffix>
> > concept user_defined_literal_r = /* to determine... */;
> > }
> >
> > where:
> >
> > - `R` is the returning type(can be optional in the form of an extra
> concept for the users that might don't care about the returning type of the
> user-defined literal)
> >
> > - `param` defines the parameter declaration clause and
> >
> > - `suffix` defines the user-defined suffix used for the user-defined
> literal
> >
>
feature yet to propose) would be:
#include <cstddef>
#include <type_traits>
namespace detailed{
template<class, class> struct types_to_params{
static_assert(false, "invalid types!");
};
template<> struct types_to_params<const char*, void>{
static consteval std::user_defined_literal_parameters value(){
return std::user_defined_literal_parameters::const_char_pointer;
}
};
template<> struct types_to_params<unsigned long long int, void>{
static consteval std::user_defined_literal_parameters value(){
return std::user_defined_literal_parameters::unsigned_long_long_int;
}
};
template<> struct types_to_params<long double, void>{
static consteval std::user_defined_literal_parameters value(){
return std::user_defined_literal_parameters::long_double;
}
};
template<> struct types_to_params<char, void>{
static consteval std::user_defined_literal_parameters value(){
return std::user_defined_literal_parameters::char_;
}
};
template<> struct types_to_params<wchar_t, void>{
static consteval std::user_defined_literal_parameters value(){
return std::user_defined_literal_parameters::wchar_t_;
}
};
template<> struct types_to_params<char8_t, void>{
static consteval std::user_defined_literal_parameters value(){
return std::user_defined_literal_parameters::char8_t_;
}
};
template<> struct types_to_params<char16_t, void>{
static consteval std::user_defined_literal_parameters value(){
return std::user_defined_literal_parameters::char16_t_;
}
};
template<> struct types_to_params<char32_t, void>{
static consteval std::user_defined_literal_parameters value(){
return std::user_defined_literal_parameters::char32_t_;
}
};
template<> struct types_to_params<const char*, std::size_t>{
static consteval std::user_defined_literal_parameters value(){
return std::user_defined_literal_parameters::const_char_pointer_with_size;
}
};
template<> struct types_to_params<const wchar_t*, std::size_t>{
static consteval std::user_defined_literal_parameters value(){
return std::user_defined_literal_parameters::const_wchar_t_pointer_with_size
;
}
};
template<> struct types_to_params<char8_t, std::size_t>{
static consteval std::user_defined_literal_parameters value(){
return std::user_defined_literal_parameters::const_char8_t_pointer_with_size
;
}
};
template<> struct types_to_params<char16_t, std::size_t>{
static consteval std::user_defined_literal_parameters value(){
return
std::user_defined_literal_parameters::const_char16_t_pointer_with_size;
}
};
template<> struct types_to_params<char32_t, std::size_t>{
static consteval std::user_defined_literal_parameters value(){
return
std::user_defined_literal_parameters::const_char32_t_pointer_with_size;
}
};
}
template<class T, class U>
inline constexpr auto types_to_params = detailed::types_to_params<T,
U>::value();
template<class R, class T, const char* suffix, bool sized = true>
requires std::user_defined_literal_r<R, types_to_params<T,
std::conditional_t<sized, std::size_t, void>>, suffix>
constexpr R instantiate_usl(T t)
{
return userexpr(t, sized, suffix);
// userexpr converts the given instance, sized or not, and suffix to its
literal representation
// in the form of an expression
}
As to why the expression-checking of constraints isn't enough because it's
tedious to write and can't handle genericity, since it must define a
concept per user-defined literal suffix and per parameter clause case, e.g,
the following code is valid under GCC and Clang trunk with -std=c++23
-Werror -pedantic -Wall -Wextra:
#include <cstddef>
void operator""_km(const char*, std::size_t);
void operator""_km(unsigned long long int); void operator""_s(const char*,
std::size_t);
template<const char*>
concept user_defined_const_char_km_literal = requires{
"a"_km;
};
template<unsigned long long int>
concept user_defined_unsigned_long_long_int_km_literal = requires{
42_km;
};
template<const char*>
concept user_defined_const_char_s_literal = requires{
"a"_s;
};
El mar, 15 ago 2023 a las 17:25, Jens Maurer (<jens.maurer_at_[hidden]>)
escribió:
> Hi,
>
> Could you give a few examples how to use this facility,
> and why the usual expression-checking machinery of
> concepts isn't enough?
>
> Jens
>
>
> On 15/08/2023 17.56, veronica alphonso via Std-Proposals wrote:
> > I would like to add a feature to the concepts(or type_traits if it's a
> better fit) library, which determines whether a user-defined literal is
> defined in the actual TU given the types of the param-list and the suffix
> for it, like:
> >
> > namespace std {
> > enum class user_defined_literal_parameters : uint8_t{
> > const_char_pointer = 0u,
> > unsigned_long_long_int = 1u,
> > long_double = 2u,
> > char_ = 3u,
> > wchar_t_ = 4u,
> > char8_t_ = 5u,
> > char16_t_ = 6u,
> > char32_t_ = 7u,
> > const_char_pointer_with_size = 8u,
> > const_wchar_t_pointer_with_size = 9u,
> > const_char8_t_pointer_with_size = 10u,
> > const_char16_t_pointer_with_size = 11u,
> > const_char32_t_pointer_with_size = 12u
> > };
> >
> > template<user_defined_literal_parameters param, const char* suffix>
> > concept user_defined_literal = /* to determine... */;
> >
> > template<class R, user_defined_literal_parameters param, const char*
> suffix>
> > concept user_defined_literal_r = /* to determine... */;
> > }
> >
> > where:
> >
> > - `R` is the returning type(can be optional in the form of an extra
> concept for the users that might don't care about the returning type of the
> user-defined literal)
> >
> > - `param` defines the parameter declaration clause and
> >
> > - `suffix` defines the user-defined suffix used for the user-defined
> literal
> >
>
Received on 2023-08-15 18:05:16