Premise:
I am trying to make a Define scope that is not implemented using a macro because of the potential issues with macros. Here is my initial attempt
//version for if not defined
bool Defined()
{
return false
}
//version for if defined
bool Defined(bool anything)
{
return true;
}
And an example use case
if(Defined(_DEBUG))
{
Stuff...
}
which would replace
#ifdef _DEBUG
Stuff...
#endif
or
#define Defined() false
#define Defined(Anything) true
Benefits:
syntax is cleaner, it is scoped,
This code is not conditional, so the compiler will be able to easily optimize code sections out.
Issues
There are a few issues with this procedure, the first is the reason for this post.
Question:
You can't pass in anything that is not implicitly cast-able to a bool. Is there a way to implicitly cast any object, number, pointer, etc to a bool? I don't believe there is, but I wanted to make sure, before I continued.
You can use a generic template:
template<class T>
bool Defined(T &&) { return true; }
Related
In my code, I have repeatedly this expression:
T foo;
do_sth(foo, "foo");
I am considering stringifying the variable name, like this:
#define VARNAME(Var) (#Var)
void do_sth_new(T foo) { do_sth(foo, VARNAME(foo)); };
T foo;
do_sth_new(foo);
Is it good practice? Is there any better alternative in C++11?
As you show it, it doesn't work since VARNAME(foo) will always be "foo" (as this is the parameter's name). You have to write do_sth_new itself as macro:
#define do_sth_new(_foo) \
do { do_sth(_foo, #_foo); } while (false)
Only then will this:
T bar;
do_sth_new(bar);
generate "bar".
And no, there is no alternative to using the preprocessor since this is an operation on the lexical level. You'd need LISP-level modification of the AST in the language to have a better solution, which is unlikely to ever happen.
Sadly, no. There is still no solution (not even in C++17) to this problem. There might be something once static reflection will be added to C++. But for the time being you're stuck with the macro.
There is no real way to avoid the macro to do the stringify.
What you can do is dress it in a more c++ object-oriented way, especially if you want to do multiple different methods that take an object and its var name, and if this is a debug feature you might want to disable in production.
So I'm proposing you declare a template class DebugContextWrap, and objects of this type (or const ref) can be passed into the function as a single parameter, instead of having 2 parameters.
The one downside is that where your function code actually wants to access the actual value then you would have to perform an indirection through operator -> or data() as you do for iterators.
You could then write a macro that generates instances of DebugContextWrap - something like:
template class FooType
class DebugContextWrap
{
FooType& fooVal;
const char* debugName;
const char* debug__FILE__val;
const int debug__LINE__val;
public:
DebugContextWrap(FooType& fooVal,
const char* debugName, const char* debug__FILE__val, const int debug__LINE__val)
{ ... }
DebugContextWrap(FooType& fooVal) // implicit when caller doesn't use DEBUG_WRAP
{ ... }
FooType* operator ->()const
{ return &foo; }
FooType& operator *()const
{ return foo; }
FooType& Data()const
{ return foo; }
const char* DebugName()const
{ return debugName; }
};
#define DEBUG_WRAP(foo) \
DebugContextWrap<decltype foo>(foo, #foo, __FILE__, __LINE__)
void do_sth(const DebugContextWrap<FooType>& foo);
do_sth(DEBUG_WRAP(foovar));
C++17 has a new attribute, [[nodiscard]].
Suppose, that I have a Result struct, which has this attribute:
struct [[nodiscard]] Result {
};
Now, if I call a function which returns Result, I got a warning if I don't check the returned Result:
Result someFunction();
int main() {
someFunction(); // warning here, as I don't check someFunction's return value
}
This program generates:
warning: ignoring return value of function declared with 'nodiscard'
attribute [-Wunused-result]
So far, so good. Now suppose, that I have a special function, for which I still want to return Result, but I don't want this warning generated, if the check is omitted:
Result someNonCriticalFunction();
int main() {
someNonCriticalFunction(); // I don't want to generate a warning here
}
It is because, someNonCriticalFunction() does something non-critical (for example, something like printf - I bet that no-one checks printf's return value all the time); most cases, I don't care if it fails. But I still want it to return Result, as in some rare cases, I do need its Result.
Is it possible to do this somehow?
Possible solutions which I don't like:
I would not like calling it as (void)someNonCriticalFunction(), because this function is called a lot of times, it is awkward
creating a wrapper around someNonCriticalFunction(), which calls (void)someNonCriticalFunction(): I don't want to have a differently named function just because of this
removing [[nodiscard]] from Result, and add it to every function which returns Result
Why not make use of std::ignore from the <tuple> header—that would make the discard explicit:
[[nodiscard]] int MyFunction() { return 42; }
int main()
{
std::ignore = MyFunction();
return 0;
}
Compiler explorer of this code snippet: https://godbolt.org/z/eGPsjajz8
CPP Reference for std::ignore: https://en.cppreference.com/w/cpp/utility/tuple/ignore
I recommend the option you ruled out:
"removing [[nodiscard]] from Result, and add it to every function which returns Result."
But since you don't seem happy with it, here's another solution, using bog-standard inheritance:
struct [[nodiscard]] Result {
};
struct DiscardableResult: public Result {
};
For the functions where you can discard the result, use DiscardableResult as return type:
Result func1();
DiscardableResult func2();
func1(); // will warn
func2(); // will not warn
They say that every problem in computer science can be solved by adding another layer of indirection:
template <bool nodiscard=true>
struct Result;
template <>
struct Result<false> {
// the actual implementation
};
template <>
struct [[nodiscard]] Result<true>
: Result<false>
{
using Result<false>::Result;
};
This is effectively making Result conditionally [[nodiscard]], which allows:
Result<true> someFunction();
Result<false> someNonCriticalFunction();
int main() {
someFunction(); // warning here
someNonCriticalFunction(); // no warning here
}
Although really, this is identical to:
removing [[nodiscard]] from Result, and add it to every function which returns Result
which gets my vote to begin with.
You can suppress the warning with another C++17 attribute, namely [[maybe_unused]]
[[nodiscard]] int MyFunction() { return 42; }
int main()
{
[[maybe_unused]] auto v = MyFunction();
return 0;
}
This way you also avoid the confusing dependency to std::tuple which comes with std::ignore, even CppCoreGuidelines is openly recommending to use std::ignore for ignoring [[nodiscard]] values:
Never cast to (void) to ignore a [[nodiscard]]return value. If you
deliberately want to discard such a result, first think hard about
whether that is really a good idea (there is usually a good reason the
author of the function or of the return type used [[nodiscard]] in the
first place). If you still think it's appropriate and your code
reviewer agrees, use std::ignore = to turn off the warning which is
simple, portable, and easy to grep.
Looking at C++ reference, officially std::ignore is only specified to be used in std::tie when unpacking tuples.
While the behavior of std::ignore outside of std::tie is not formally
specified, some code guides recommend using std::ignore to avoid
warnings from unused return values of [[nodiscard]] functions.
cast the result to a (void *).
int main()
{
(void *)someFunction(); //Warning will be gone.
}
This way you "used" your result as far as the compiler is concerned. Great for when you are using a library where nodiscard has been used and you really don't care to know the result.
Found the following statement in Wiki:
C++11 introduced the concept of a constexpr-declared function; a
function which could be executed at compile time. Their return values
could be consumed by operations that require constant expressions,
such as an integer template argument. However, C++11 constexpr
functions could only contain a single expression that is returned (as
well as static_asserts and a small number of other declarations).
C++14 relaxes these restrictions. Constexpr-declared functions may now
contain the following: The conditional
...
branching statements if and switch
So, Is it actually possible to have a switch in a constexpr function in c++14/c++17? And, if possible, what syntax is for that?
For example, I'd like to have something like this:
enum class Terrain : std::uintmax_t {
ROAD,
SOIL,
GRASS,
MUD,
SNOW,
};
constexpr float
getStepPrice(Terrain const& terrain)
{
switch constexpr (terrain)
{
case Terrain::ROAD: return 1.0f;
...
}
}
Not exactly. In the case of if constexpr, you can rest assured that the resulting code has no branching. Moreover, discarded statements need not compile. Those are the guarantees I think you would expect from a true switch constexpr.
class Dog;
class Snake;
#define USE_IF
template<typename Pet>
constexpr void foo(Pet pet) {
#ifdef USE_IF
// This works
if constexpr(std::is_same_v<Pet, Dog>) pet.bark();
else pet.slither();
#else
// This doesn't
switch (std::is_same_v<Pet, Dog>) {
case true: pet.bark(); break; // <== Error if Snake
case false: pet.slither(); break; // <== Error if Dog
}
#else
}
BTW, I'm being a little nit-picky vis-a-vis Baum's accepted answer, which is fine, for practical puposes. I suspect you'd find good compilers will elide logically impossible bits from a switch-case statement with constexpr functions, as well as even non-constexpr inlined functions.
So, Is it actually possible to have a switch in a constexpr function in c++14/c++17?
Yes.
And, if possible, what syntax is for that?
There is absolutely nothing special about the syntax, it's just a normal switch. Like this:
constexpr int fun (int i) {
switch(i) {
case 0: return 7;
default: return 5;
}
}
int main () {
int arr[fun(3)];
}
// Example assert function
inline void assertImpl(bool mExpr, const std::string& mMsg) {
if(!mExpr) { printMsg(mMsg); abortExecution(); }
}
// Wrapper macro
#ifdef NDEBUG
#define MY_ASSERT(...) do{ ; }while(false)
#else
#define MY_ASSERT(...) assertImpl(__VA_ARGS__)
#endif
Consider the case where mExpr or mMsg are not-pure expressions - is there a way to force the compiler to optimize them out anyway?
bool globalState{false};
bool pureExpression() { return false; }
bool impureExpression() { globalState = !globalState; return false; }
// ...
// This will very likely be optimized out with (NDEBUG == 0)
MY_ASSERT(pureExpression());
// Will this be optimized out with (NDEBUG == 0)
MY_ASSERT(impureExpression());
What do compilers usually do in a situation where an impure expression is "discarded"?
Is there a way to make 100% sure that pure expressions get optimized out?
Is there a way to make 100% sure that impure expressions get optimized out or never get optimized out?
After macro expansion, your call to impureExpression() no longer exists: it's not part of the macro expansion result. If the call to your function isn't there, the function won't be called, on all conforming implementations, at any optimisation level, as long as NDEBUG is defined.
Note: you talk about NDEBUG == 0, but if that is what you want the condition to be, your #ifdef NDEBUG condition is incorrect. #ifdef tests whether the macro is defined, and pays no attention to what the definition is.
The optimizer is not involved here. In the macro that is enabled with NDEBUG, the arguments are discarded regardless.
I'd like to keep my code compilable both on legacy C++ (C++ code using "NULL") and new C++11 standard (C++ code using "nullptr")
I'm using GCC, but planning to recompile the whole codebase also for VS when I'll finish most important things.
Should I expect both GCC and VS will do something like
#define NULL nullptr
Or Is better I'll do that myself (using of course a different name, where MY_LIB will be replaced by my library suffix)?
#ifndef nullptr
#define MY_LIB_NULL NULL
#else
#define MY_LIB_NULL nullptr
#endif
What I want to achieve is code that compiles regardless of wich C++11 features have been implemented or not (and since i'm not using templates, there are very few of them).
For example the keywords "override" and "final" are already done.
MY_LIB_OVERRIDE //macro, defines to "override" if c++11 is present.
MY_LIB_FINAL //macro, defines to "final" if c++11 is present.
I'm asking the question because I know the "nullptr" question is a bit strange, so maybe just doing the same I already did for override and final, is wrong. Needs opinions about that. Any help is wellcome.
You could probably create a "false" my_nullptr of type my_nullptr_t the following way:
const class my_nullptr_t
{
public:
/* Return 0 for any class pointer */
template<typename T>
operator T*() const
{
return 0;
}
/* Return 0 for any member pointer */
template<typename T, typename U>
operator T U::*() const
{
return 0;
}
/* Safe boolean conversion */
operator void*() const
{
return 0;
}
private:
/* Not allowed to get the address */
void operator&() const;
} my_nullptr = {};
This works with C++03 and C++11 and should always be safe, whichever C++11 features are implemented. That solution was actually already discussed in this topic that proposed a version of nullptr_t based on the Official proposal.
NULL is a macro that expands to a null pointer constant. It still works just like it used to. Code that has to work with non-C++11 compilers should use NULL.
I think following will works:
#include <cstddef>
#ifndef MY_LIB_NULL
#ifndef NULL //check for NULL
#define MY_LIB_NULL nullptr
#else
#define MY_LIB_NULL NULL ///use NULL if present
#endif
#endif
basically I check for "NULL". wich is a macro and can be checked, until the compiler is shipped with that macro (likely to be), than it's valid using the macro, when compiler will only provides "nullptr" and no longer have NULL then nullptr is used (maybe in a far future, but seems we can happily continue to use NULL!)
I think that's safer than redefining "nullptr" (like most people trying to do)