A NOT macro for negative conditions
Clash Royale CLAN TAG#URR8PPP
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;
up vote
6
down vote
favorite
Motivation
I typically try to avoid using !
in if-statements, because (to me) it seems easy to overlook. So, I'll usually just spell it out instead, ex: if (done == false)
instead of if (!done)
. While that makes the intention more obvious, it doesn't read very fluidly.
Macro code
For those cases I wrote the following macro:
#define NOT(x) ((x) == false)
The outer parentheses make it possible to use NOT(cond)
without additional parentheses in if
and make it less error prone:
if NOT(condition)
...
Complete example of macro usage
#include <iostream>
#define NOT(x) ((x) == false)
bool successful() return false;
int main(int argc, char **argv)
if NOT(successful())
std::cout << "Warning! Self-destruction activated...n";
const bool this_is_true = true;
if NOT(this_is_true)
std::cout << "True is false.n";
return EXIT_SUCCESS;
Concerns
While this works, I have some concerns:
From a best-practices or clean code perspective, is this frowned upon?
How are macros generally viewed, or reported on, in code analysis tools? We are considering employing a system called CAST-AIP for code analysis and, while I am strongly in favor of doing so, I am wondering how many volumes of practice violations my reports are going to be.
c++
 |Â
show 9 more comments
up vote
6
down vote
favorite
Motivation
I typically try to avoid using !
in if-statements, because (to me) it seems easy to overlook. So, I'll usually just spell it out instead, ex: if (done == false)
instead of if (!done)
. While that makes the intention more obvious, it doesn't read very fluidly.
Macro code
For those cases I wrote the following macro:
#define NOT(x) ((x) == false)
The outer parentheses make it possible to use NOT(cond)
without additional parentheses in if
and make it less error prone:
if NOT(condition)
...
Complete example of macro usage
#include <iostream>
#define NOT(x) ((x) == false)
bool successful() return false;
int main(int argc, char **argv)
if NOT(successful())
std::cout << "Warning! Self-destruction activated...n";
const bool this_is_true = true;
if NOT(this_is_true)
std::cout << "True is false.n";
return EXIT_SUCCESS;
Concerns
While this works, I have some concerns:
From a best-practices or clean code perspective, is this frowned upon?
How are macros generally viewed, or reported on, in code analysis tools? We are considering employing a system called CAST-AIP for code analysis and, while I am strongly in favor of doing so, I am wondering how many volumes of practice violations my reports are going to be.
c++
12
Best: Never use macros at all with c++. Don't obfuscate semantics.
â ÃÂìýÃÂñ á¿¥Ã栨Â
Apr 13 at 18:01
2
@ÃÂìýÃÂÃ񠨝õῠthere are some very, very, very rare cases where macros can improve code quality and the alternative is more error prone than the macro. This isn't one of them.
â Zeta
Apr 13 at 18:05
4
I'm not sure what more context one can provide here... this question shouldn't have been closed. It's a simple, one-liner macro, what else one can say about it but providing an example?
â t3chb0t
Apr 13 at 18:08
2
From codereview.stackexchange.com/help/dont-ask: "Best practices in general: It's OK to ask "Does this code follow common best practices?""
â Blair Fonville
Apr 13 at 18:14
2
Close-reason discussion on meta
â t3chb0t
Apr 13 at 18:16
 |Â
show 9 more comments
up vote
6
down vote
favorite
up vote
6
down vote
favorite
Motivation
I typically try to avoid using !
in if-statements, because (to me) it seems easy to overlook. So, I'll usually just spell it out instead, ex: if (done == false)
instead of if (!done)
. While that makes the intention more obvious, it doesn't read very fluidly.
Macro code
For those cases I wrote the following macro:
#define NOT(x) ((x) == false)
The outer parentheses make it possible to use NOT(cond)
without additional parentheses in if
and make it less error prone:
if NOT(condition)
...
Complete example of macro usage
#include <iostream>
#define NOT(x) ((x) == false)
bool successful() return false;
int main(int argc, char **argv)
if NOT(successful())
std::cout << "Warning! Self-destruction activated...n";
const bool this_is_true = true;
if NOT(this_is_true)
std::cout << "True is false.n";
return EXIT_SUCCESS;
Concerns
While this works, I have some concerns:
From a best-practices or clean code perspective, is this frowned upon?
How are macros generally viewed, or reported on, in code analysis tools? We are considering employing a system called CAST-AIP for code analysis and, while I am strongly in favor of doing so, I am wondering how many volumes of practice violations my reports are going to be.
c++
Motivation
I typically try to avoid using !
in if-statements, because (to me) it seems easy to overlook. So, I'll usually just spell it out instead, ex: if (done == false)
instead of if (!done)
. While that makes the intention more obvious, it doesn't read very fluidly.
Macro code
For those cases I wrote the following macro:
#define NOT(x) ((x) == false)
The outer parentheses make it possible to use NOT(cond)
without additional parentheses in if
and make it less error prone:
if NOT(condition)
...
Complete example of macro usage
#include <iostream>
#define NOT(x) ((x) == false)
bool successful() return false;
int main(int argc, char **argv)
if NOT(successful())
std::cout << "Warning! Self-destruction activated...n";
const bool this_is_true = true;
if NOT(this_is_true)
std::cout << "True is false.n";
return EXIT_SUCCESS;
Concerns
While this works, I have some concerns:
From a best-practices or clean code perspective, is this frowned upon?
How are macros generally viewed, or reported on, in code analysis tools? We are considering employing a system called CAST-AIP for code analysis and, while I am strongly in favor of doing so, I am wondering how many volumes of practice violations my reports are going to be.
c++
edited Apr 13 at 18:16
Zeta
14.3k23267
14.3k23267
asked Apr 13 at 17:53
Blair Fonville
1446
1446
12
Best: Never use macros at all with c++. Don't obfuscate semantics.
â ÃÂìýÃÂñ á¿¥Ã栨Â
Apr 13 at 18:01
2
@ÃÂìýÃÂÃ񠨝õῠthere are some very, very, very rare cases where macros can improve code quality and the alternative is more error prone than the macro. This isn't one of them.
â Zeta
Apr 13 at 18:05
4
I'm not sure what more context one can provide here... this question shouldn't have been closed. It's a simple, one-liner macro, what else one can say about it but providing an example?
â t3chb0t
Apr 13 at 18:08
2
From codereview.stackexchange.com/help/dont-ask: "Best practices in general: It's OK to ask "Does this code follow common best practices?""
â Blair Fonville
Apr 13 at 18:14
2
Close-reason discussion on meta
â t3chb0t
Apr 13 at 18:16
 |Â
show 9 more comments
12
Best: Never use macros at all with c++. Don't obfuscate semantics.
â ÃÂìýÃÂñ á¿¥Ã栨Â
Apr 13 at 18:01
2
@ÃÂìýÃÂÃ񠨝õῠthere are some very, very, very rare cases where macros can improve code quality and the alternative is more error prone than the macro. This isn't one of them.
â Zeta
Apr 13 at 18:05
4
I'm not sure what more context one can provide here... this question shouldn't have been closed. It's a simple, one-liner macro, what else one can say about it but providing an example?
â t3chb0t
Apr 13 at 18:08
2
From codereview.stackexchange.com/help/dont-ask: "Best practices in general: It's OK to ask "Does this code follow common best practices?""
â Blair Fonville
Apr 13 at 18:14
2
Close-reason discussion on meta
â t3chb0t
Apr 13 at 18:16
12
12
Best: Never use macros at all with c++. Don't obfuscate semantics.
â ÃÂìýÃÂñ á¿¥Ã栨Â
Apr 13 at 18:01
Best: Never use macros at all with c++. Don't obfuscate semantics.
â ÃÂìýÃÂñ á¿¥Ã栨Â
Apr 13 at 18:01
2
2
@ÃÂìýÃÂÃ񠨝õῠthere are some very, very, very rare cases where macros can improve code quality and the alternative is more error prone than the macro. This isn't one of them.
â Zeta
Apr 13 at 18:05
@ÃÂìýÃÂÃ񠨝õῠthere are some very, very, very rare cases where macros can improve code quality and the alternative is more error prone than the macro. This isn't one of them.
â Zeta
Apr 13 at 18:05
4
4
I'm not sure what more context one can provide here... this question shouldn't have been closed. It's a simple, one-liner macro, what else one can say about it but providing an example?
â t3chb0t
Apr 13 at 18:08
I'm not sure what more context one can provide here... this question shouldn't have been closed. It's a simple, one-liner macro, what else one can say about it but providing an example?
â t3chb0t
Apr 13 at 18:08
2
2
From codereview.stackexchange.com/help/dont-ask: "Best practices in general: It's OK to ask "Does this code follow common best practices?""
â Blair Fonville
Apr 13 at 18:14
From codereview.stackexchange.com/help/dont-ask: "Best practices in general: It's OK to ask "Does this code follow common best practices?""
â Blair Fonville
Apr 13 at 18:14
2
2
Close-reason discussion on meta
â t3chb0t
Apr 13 at 18:16
Close-reason discussion on meta
â t3chb0t
Apr 13 at 18:16
 |Â
show 9 more comments
2 Answers
2
active
oldest
votes
up vote
22
down vote
accepted
Something like if (foo == false)
will always be frowned upon. If you find the negation hard to spot you might consider using not
instead (see this for more info).
E.g. if (not foo)
From what I've seen macros are generally discouraged as they tend to obfuscate code and are not typesafe.
I don't see any sense in waiting to accept this. I can't believe I never knew about these alternative operators. One thing that confuses me is where it reads: "Because in C++ these are built into the language, the C++ version of <iso646.h>, as well as <ciso646>, does not define anything.". Yet it doesn't appear to work without including one.
â Blair Fonville
Apr 13 at 18:48
@BlairFonville MSVC? AFAIK they don't (or at least didn't) implement that correctly. You can probably use/FI
(force include) to make it work without it.
â Justin
Apr 13 at 19:49
@Justin You guessed it, VS2017. When I followed the not operator, I found that it resolves to iso646.h : #define not !. Where iso646.h, is included in their ciso646 header. I'll look into /FI, but from it's name, it sounds like it just going to save me the one "#include <ciso646>" line, by doing it for me.
â Blair Fonville
Apr 13 at 19:58
@BlairFonville Yes, that's what it would do. The good thing about that is that it would improve the quality of the code, as your build system would be taking care of the non-standard stuff.
â Justin
Apr 13 at 20:02
1
For some reason habits that hinder readability are traditional and very tenacious in the C/C++ world. The keywordsnot
,and
andor
(as well as several others) as alternative representations of!
,&&
and||
exist for ages, but few seem to know about them, let alone use them; personally I always use them (except then&&
means "rvalue reference"). I also always avoid implicit conversion fromint
tobool
(writingif (i!=0)
if that is what I mean), though that does not prevent me from occasionally getting bitten by an unintended implicit conversion.
â Marc van Leeuwen
Apr 14 at 6:58
 |Â
show 5 more comments
up vote
-4
down vote
why not just
#define NOT !
It would be simpler to use.
3
or just #include<iso646.h>, which does precisely that - per the discussion in comments of yuriâÂÂs answer.
â Blair Fonville
Apr 14 at 2:38
add a comment |Â
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
22
down vote
accepted
Something like if (foo == false)
will always be frowned upon. If you find the negation hard to spot you might consider using not
instead (see this for more info).
E.g. if (not foo)
From what I've seen macros are generally discouraged as they tend to obfuscate code and are not typesafe.
I don't see any sense in waiting to accept this. I can't believe I never knew about these alternative operators. One thing that confuses me is where it reads: "Because in C++ these are built into the language, the C++ version of <iso646.h>, as well as <ciso646>, does not define anything.". Yet it doesn't appear to work without including one.
â Blair Fonville
Apr 13 at 18:48
@BlairFonville MSVC? AFAIK they don't (or at least didn't) implement that correctly. You can probably use/FI
(force include) to make it work without it.
â Justin
Apr 13 at 19:49
@Justin You guessed it, VS2017. When I followed the not operator, I found that it resolves to iso646.h : #define not !. Where iso646.h, is included in their ciso646 header. I'll look into /FI, but from it's name, it sounds like it just going to save me the one "#include <ciso646>" line, by doing it for me.
â Blair Fonville
Apr 13 at 19:58
@BlairFonville Yes, that's what it would do. The good thing about that is that it would improve the quality of the code, as your build system would be taking care of the non-standard stuff.
â Justin
Apr 13 at 20:02
1
For some reason habits that hinder readability are traditional and very tenacious in the C/C++ world. The keywordsnot
,and
andor
(as well as several others) as alternative representations of!
,&&
and||
exist for ages, but few seem to know about them, let alone use them; personally I always use them (except then&&
means "rvalue reference"). I also always avoid implicit conversion fromint
tobool
(writingif (i!=0)
if that is what I mean), though that does not prevent me from occasionally getting bitten by an unintended implicit conversion.
â Marc van Leeuwen
Apr 14 at 6:58
 |Â
show 5 more comments
up vote
22
down vote
accepted
Something like if (foo == false)
will always be frowned upon. If you find the negation hard to spot you might consider using not
instead (see this for more info).
E.g. if (not foo)
From what I've seen macros are generally discouraged as they tend to obfuscate code and are not typesafe.
I don't see any sense in waiting to accept this. I can't believe I never knew about these alternative operators. One thing that confuses me is where it reads: "Because in C++ these are built into the language, the C++ version of <iso646.h>, as well as <ciso646>, does not define anything.". Yet it doesn't appear to work without including one.
â Blair Fonville
Apr 13 at 18:48
@BlairFonville MSVC? AFAIK they don't (or at least didn't) implement that correctly. You can probably use/FI
(force include) to make it work without it.
â Justin
Apr 13 at 19:49
@Justin You guessed it, VS2017. When I followed the not operator, I found that it resolves to iso646.h : #define not !. Where iso646.h, is included in their ciso646 header. I'll look into /FI, but from it's name, it sounds like it just going to save me the one "#include <ciso646>" line, by doing it for me.
â Blair Fonville
Apr 13 at 19:58
@BlairFonville Yes, that's what it would do. The good thing about that is that it would improve the quality of the code, as your build system would be taking care of the non-standard stuff.
â Justin
Apr 13 at 20:02
1
For some reason habits that hinder readability are traditional and very tenacious in the C/C++ world. The keywordsnot
,and
andor
(as well as several others) as alternative representations of!
,&&
and||
exist for ages, but few seem to know about them, let alone use them; personally I always use them (except then&&
means "rvalue reference"). I also always avoid implicit conversion fromint
tobool
(writingif (i!=0)
if that is what I mean), though that does not prevent me from occasionally getting bitten by an unintended implicit conversion.
â Marc van Leeuwen
Apr 14 at 6:58
 |Â
show 5 more comments
up vote
22
down vote
accepted
up vote
22
down vote
accepted
Something like if (foo == false)
will always be frowned upon. If you find the negation hard to spot you might consider using not
instead (see this for more info).
E.g. if (not foo)
From what I've seen macros are generally discouraged as they tend to obfuscate code and are not typesafe.
Something like if (foo == false)
will always be frowned upon. If you find the negation hard to spot you might consider using not
instead (see this for more info).
E.g. if (not foo)
From what I've seen macros are generally discouraged as they tend to obfuscate code and are not typesafe.
answered Apr 13 at 18:02
yuri
3,3862832
3,3862832
I don't see any sense in waiting to accept this. I can't believe I never knew about these alternative operators. One thing that confuses me is where it reads: "Because in C++ these are built into the language, the C++ version of <iso646.h>, as well as <ciso646>, does not define anything.". Yet it doesn't appear to work without including one.
â Blair Fonville
Apr 13 at 18:48
@BlairFonville MSVC? AFAIK they don't (or at least didn't) implement that correctly. You can probably use/FI
(force include) to make it work without it.
â Justin
Apr 13 at 19:49
@Justin You guessed it, VS2017. When I followed the not operator, I found that it resolves to iso646.h : #define not !. Where iso646.h, is included in their ciso646 header. I'll look into /FI, but from it's name, it sounds like it just going to save me the one "#include <ciso646>" line, by doing it for me.
â Blair Fonville
Apr 13 at 19:58
@BlairFonville Yes, that's what it would do. The good thing about that is that it would improve the quality of the code, as your build system would be taking care of the non-standard stuff.
â Justin
Apr 13 at 20:02
1
For some reason habits that hinder readability are traditional and very tenacious in the C/C++ world. The keywordsnot
,and
andor
(as well as several others) as alternative representations of!
,&&
and||
exist for ages, but few seem to know about them, let alone use them; personally I always use them (except then&&
means "rvalue reference"). I also always avoid implicit conversion fromint
tobool
(writingif (i!=0)
if that is what I mean), though that does not prevent me from occasionally getting bitten by an unintended implicit conversion.
â Marc van Leeuwen
Apr 14 at 6:58
 |Â
show 5 more comments
I don't see any sense in waiting to accept this. I can't believe I never knew about these alternative operators. One thing that confuses me is where it reads: "Because in C++ these are built into the language, the C++ version of <iso646.h>, as well as <ciso646>, does not define anything.". Yet it doesn't appear to work without including one.
â Blair Fonville
Apr 13 at 18:48
@BlairFonville MSVC? AFAIK they don't (or at least didn't) implement that correctly. You can probably use/FI
(force include) to make it work without it.
â Justin
Apr 13 at 19:49
@Justin You guessed it, VS2017. When I followed the not operator, I found that it resolves to iso646.h : #define not !. Where iso646.h, is included in their ciso646 header. I'll look into /FI, but from it's name, it sounds like it just going to save me the one "#include <ciso646>" line, by doing it for me.
â Blair Fonville
Apr 13 at 19:58
@BlairFonville Yes, that's what it would do. The good thing about that is that it would improve the quality of the code, as your build system would be taking care of the non-standard stuff.
â Justin
Apr 13 at 20:02
1
For some reason habits that hinder readability are traditional and very tenacious in the C/C++ world. The keywordsnot
,and
andor
(as well as several others) as alternative representations of!
,&&
and||
exist for ages, but few seem to know about them, let alone use them; personally I always use them (except then&&
means "rvalue reference"). I also always avoid implicit conversion fromint
tobool
(writingif (i!=0)
if that is what I mean), though that does not prevent me from occasionally getting bitten by an unintended implicit conversion.
â Marc van Leeuwen
Apr 14 at 6:58
I don't see any sense in waiting to accept this. I can't believe I never knew about these alternative operators. One thing that confuses me is where it reads: "Because in C++ these are built into the language, the C++ version of <iso646.h>, as well as <ciso646>, does not define anything.". Yet it doesn't appear to work without including one.
â Blair Fonville
Apr 13 at 18:48
I don't see any sense in waiting to accept this. I can't believe I never knew about these alternative operators. One thing that confuses me is where it reads: "Because in C++ these are built into the language, the C++ version of <iso646.h>, as well as <ciso646>, does not define anything.". Yet it doesn't appear to work without including one.
â Blair Fonville
Apr 13 at 18:48
@BlairFonville MSVC? AFAIK they don't (or at least didn't) implement that correctly. You can probably use
/FI
(force include) to make it work without it.â Justin
Apr 13 at 19:49
@BlairFonville MSVC? AFAIK they don't (or at least didn't) implement that correctly. You can probably use
/FI
(force include) to make it work without it.â Justin
Apr 13 at 19:49
@Justin You guessed it, VS2017. When I followed the not operator, I found that it resolves to iso646.h : #define not !. Where iso646.h, is included in their ciso646 header. I'll look into /FI, but from it's name, it sounds like it just going to save me the one "#include <ciso646>" line, by doing it for me.
â Blair Fonville
Apr 13 at 19:58
@Justin You guessed it, VS2017. When I followed the not operator, I found that it resolves to iso646.h : #define not !. Where iso646.h, is included in their ciso646 header. I'll look into /FI, but from it's name, it sounds like it just going to save me the one "#include <ciso646>" line, by doing it for me.
â Blair Fonville
Apr 13 at 19:58
@BlairFonville Yes, that's what it would do. The good thing about that is that it would improve the quality of the code, as your build system would be taking care of the non-standard stuff.
â Justin
Apr 13 at 20:02
@BlairFonville Yes, that's what it would do. The good thing about that is that it would improve the quality of the code, as your build system would be taking care of the non-standard stuff.
â Justin
Apr 13 at 20:02
1
1
For some reason habits that hinder readability are traditional and very tenacious in the C/C++ world. The keywords
not
, and
and or
(as well as several others) as alternative representations of !
, &&
and ||
exist for ages, but few seem to know about them, let alone use them; personally I always use them (except then &&
means "rvalue reference"). I also always avoid implicit conversion from int
to bool
(writing if (i!=0)
if that is what I mean), though that does not prevent me from occasionally getting bitten by an unintended implicit conversion.â Marc van Leeuwen
Apr 14 at 6:58
For some reason habits that hinder readability are traditional and very tenacious in the C/C++ world. The keywords
not
, and
and or
(as well as several others) as alternative representations of !
, &&
and ||
exist for ages, but few seem to know about them, let alone use them; personally I always use them (except then &&
means "rvalue reference"). I also always avoid implicit conversion from int
to bool
(writing if (i!=0)
if that is what I mean), though that does not prevent me from occasionally getting bitten by an unintended implicit conversion.â Marc van Leeuwen
Apr 14 at 6:58
 |Â
show 5 more comments
up vote
-4
down vote
why not just
#define NOT !
It would be simpler to use.
3
or just #include<iso646.h>, which does precisely that - per the discussion in comments of yuriâÂÂs answer.
â Blair Fonville
Apr 14 at 2:38
add a comment |Â
up vote
-4
down vote
why not just
#define NOT !
It would be simpler to use.
3
or just #include<iso646.h>, which does precisely that - per the discussion in comments of yuriâÂÂs answer.
â Blair Fonville
Apr 14 at 2:38
add a comment |Â
up vote
-4
down vote
up vote
-4
down vote
why not just
#define NOT !
It would be simpler to use.
why not just
#define NOT !
It would be simpler to use.
edited Apr 14 at 4:04
Sam Onela
5,78461544
5,78461544
answered Apr 14 at 2:27
somerandomdudeontheinternet
1
1
3
or just #include<iso646.h>, which does precisely that - per the discussion in comments of yuriâÂÂs answer.
â Blair Fonville
Apr 14 at 2:38
add a comment |Â
3
or just #include<iso646.h>, which does precisely that - per the discussion in comments of yuriâÂÂs answer.
â Blair Fonville
Apr 14 at 2:38
3
3
or just #include<iso646.h>, which does precisely that - per the discussion in comments of yuriâÂÂs answer.
â Blair Fonville
Apr 14 at 2:38
or just #include<iso646.h>, which does precisely that - per the discussion in comments of yuriâÂÂs answer.
â Blair Fonville
Apr 14 at 2:38
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f192000%2fa-not-macro-for-negative-conditions%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
12
Best: Never use macros at all with c++. Don't obfuscate semantics.
â ÃÂìýÃÂñ á¿¥Ã栨Â
Apr 13 at 18:01
2
@ÃÂìýÃÂÃ񠨝õῠthere are some very, very, very rare cases where macros can improve code quality and the alternative is more error prone than the macro. This isn't one of them.
â Zeta
Apr 13 at 18:05
4
I'm not sure what more context one can provide here... this question shouldn't have been closed. It's a simple, one-liner macro, what else one can say about it but providing an example?
â t3chb0t
Apr 13 at 18:08
2
From codereview.stackexchange.com/help/dont-ask: "Best practices in general: It's OK to ask "Does this code follow common best practices?""
â Blair Fonville
Apr 13 at 18:14
2
Close-reason discussion on meta
â t3chb0t
Apr 13 at 18:16