Just like in the topic: Is there a way to create a user-defined-literal from std::initializer_list
?
I am trying to do something like that:
template <typename T> inline
std::initializer_list<T> const & operator "" _lit(std::initializer_list<T> const & list)
{
return std::move(list); // I am not sure, but this line might cause undefined behavior... well I'll think about it latter...
}
int main()
{
{ 10, 20, 30, 40 }_lit // Error: identifier '_lit' is undefined;
return 0;
}
But it seems compiler doesn't understand that I am trying to call operator""_lit({10, 20, 30, 40});
Is there any way to fix it?
EDIT:
I am sorry, it turns out this is just another example of XY problem ...
Let me elaborate
I am trying to "expand" current C++ syntax (it's a fun little project...)
The main idea is to simplify this:
if ((val_1 == value) && (val_2 == value) && (val_3 == value)) { /* ... */ }
into somehting along the lines:
if (std::initializer_list<T>{val_1, val_2, val_3} == value)
ofc I am providing an additional operator:
template <typename T> inline
bool operator==(std::initializer_list<T> const & list, T const & ref)
{
for (auto const & element : list)
{
if (element == ref) { /* Do nothing. */ }
else
{
return false;
}
}
return true;
}
Everything would be fine and nice, but I dislike the need to type std::initializer_list<T>
in front of a curly bracket... Otherwise, the compiler chooses the default version of operator==()
and I get a compilation error...
Literals come here as an idea to change if (std::initializer_list<T>{val_1, val_2, val_3} == value)
into if ({val_1, val_2, val_3}_lit == value)
template<class T, std::size_t N>
struct any_of:std::array<T, N> {
#define MAKE_OPERATOR( OPERATOR ) \
template<class U, \
std::enable_if_t< std::is_same<void, std::void_t< \
decltype( std::declval<T const&>() == std::declval<U const&>() ) \
>>{}, bool> =true \
> \
friend bool operator OPERATOR ( any_of const& lhs, U const& rhs) { \
return std::any_of( \
lhs.begin(), lhs.end(), \
[&](auto&& lhs){ return lhs OPERATOR rhs; } \
); \
} \
template<class U, \
std::enable_if_t< std::is_same<void, std::void_t< \
decltype( std::declval<U const&>() == std::declval<T const&>() ) \
>>{} && !std::is_same< U, any_of >{} , bool> =true \
> \
friend bool operator OPERATOR ( U const& lhs, any_of const& rhs) { \
return std::any_of( \
rhs.begin(), rhs.end(), \
[&](auto&& rhs){ return lhs OPERATOR rhs; } \
); \
}
MAKE_OPERATOR(==)
MAKE_OPERATOR(!=)
MAKE_OPERATOR(<)
MAKE_OPERATOR(<=)
MAKE_OPERATOR(>=)
MAKE_OPERATOR(>)
#undef MAKE_OPERATOR
explicit any_of( std::array<T, N> arr):std::array<T, N>(std::move(arr)) {}
template<class...Ts>
explicit any_of( T t, Ts... ts ):std::array<T, N>{ std::move(t), std::move(ts)... } {}
any_of( any_of const& )=delete;
any_of& operator=( any_of const& )=delete;
any_of()=delete;
};
template<class T, std::size_t N>
any_of(T(&)[N]) -> any_of<T,N>;
template<class T, class...Ts>
any_of(T, Ts...) -> any_of<T, 1+sizeof...(Ts)>;
test code:
if (any_of{1,2,3} == 2) {
std::cout << "2 is there\n";
}
if (! (any_of{1,2,3} == 7) ){
std::cout << "7 is not there\n";
}
if (any_of{1,2,3} == any_of{5,6,1}) {
std::cout << "overlap!\n";
}
if (!(any_of{1,2,3} == any_of{5,6,7})) {
std::cout << "no overlap!\n";
}
Live example.
Output in c++17 compiler:
2 is there 7 is not there overlap! no overlap!
The various comparison operators are all supported.
Cross-type double any_of, like:
any_of{1,2,3} == any_of{3.14, 5.7, 1.0}
will fail to compile because both ==
of both any_of
work.
You can't make a user defined literal for a std::initializer_list
. Luckily though C++17 gives a new really cool tool that will help us out. Class template argument deduction allows us to just use the name of a class template, and the compiler will figure out what the template parameters need to be so we don't have to specify them. This means you could leverage std::array
and your code would become
template<typename T, std::size_t N>
bool operator==(std::array<T, N> const & list, T const & ref)
{
for(auto const& e : list)
if (e != ref)
return false;
return true;
}
int main()
{
using std::array;
if (array{4,4,4,4,4} == 4)
std::cout << "all 4";
}
And besides the using statement it is only an extra character between _lit
and array
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With