I am trying to understand the use of static_assert and assert and what the difference is between them, however there are very little sources/explantions about this
here is some code
// ConsoleApplication3.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "conio.h"
#include "cassert"
#include "iostream"
int main()
{
assert(2+2==4);
std::cout << "Execution continues past the first assert\n";
assert(2+2==5);
std::cout << "Execution continues past the second assert\n";
_getch();
}
comments on redundency will be appreciated(since I am learning "how to c++")
output in cmd
Execution continues past the first assert
Assertion failed: 2+2==5, file c:\users\charles\documents\visual studio 2012\pro
jects\consoleapplication3\consoleapplication3\consoleapplication3.cpp, line 14
I have been trying to find out the different mehtods and uses of it, but as far as I understand it is a runtime check and another "type" of if statement
could someone just clarify the use and explain what each one does and they difference?
You can think of assertions as sanity checks. You know that some condition should be true unless you've screwed something up, so the assertion should pass. If you have indeed screwed something up, the assertion will fail and you'll be told that something is wrong. It's just there to ensure the validity of your code.
A static_assert can be used when the condition is a constant expression. This basically means that the compiler is able to evaluate the assertion before the program ever actually runs. You will be alerted that a static_assert has failed at compile-time, whereas a normal assert will only fail at run time. In your example, you could have used a static_assert, because the expressions 2+2==4 and 2+2==5 are both constant expressions.
static_asserts are useful for checking compile-time constructs such as template parameters. For example, you could assert that a given template argument T must be a POD type with something like:
static_assert(std::is_pod<T>::value, "T must be a POD type");
Note that you generally only want run-time assertions to be checked during debugging, so you can disable assert by #defineing NDEBUG.
assert() is a macro whose expansion depends on whether macro NDEBUG is defined. If so, assert() doesn't expand to anything - it's a no-op. When NDEBUG is not defined, assert(x) expands into a runtime check, something like this:
if (!x) cause_runtime_to_abort()
It is common to define NDEBUG in "release" builds and leave it undefined in "debug" builds. That way, assert()s are only executed in debug code and do not make it into release code at all. You normally use assert() to check things which should always be true - a function's preconditions and postconditions or a class's invariants, for example. A failed assert(x) should mean "the programmer thought that x holds, but a bug somewhere in the code (or in their reasoning) made that untrue."
static_assert() (which was introduced in C++11) is a keyword - similar to e.g. typedef. It can only be used on compile-time expressions, and if it fails, it results in a compilation error. It does not result in any object code and is not executed at all.
static_assert() is primarily useful in templates, if you want to prevent instantiating a template incorrectly. For example:
template <class IntType>
IntType foo(IntType x)
{
static_assert(std::is_integral<IntType>::value, "foo() may be used with integral types only.");
// rest of the code
}
That way, trying to call foo() with e.g. a float will result in a compile-time error with a sensible message.
Occasionally, static_assert() can also be useful outside of templates, e.g. like this:
static_assert(sizeof(void*) > 4, "This code does not work in 32 bits");
a static_assert is evaluated at compile time, an assert is evaluated an runtime.
I doubt you cannot find any sources for this, but I’ll nevertheless give some explanation.
assert is for runtime checks which should never ever fail. If they fail, the program will terminate ungracefully. You can disable assertions for a release build by specifying a compile time flag. As assertions should never fail (they are assertions after all), in a working program, that should not make any difference. However, the expressions inside an assert must not have side effects, because there is no guarantee that they are executed. Example:
unsigned int add_non_negative_numbers(int a, int b)
{
// good
assert(a > 0);
assert(b > 0);
return (unsigned int)a + (unsigned int)b;
}
void checked_read(int fd, char *buffer, int count)
{
// BAD: if assertions are disabled, read() will _not_ be called
assert(read(fd, buffer, count) == count);
/* better: not perfect though, because read can always fail
int read_bytes = read(fd, buffer, count);
assert(read_bytes == count);
*/
}
static_assert is new and can be used to perform compile time checks. They will produce a compiler error when they fail and block the program from compiling:
static_assert(sizeof(char) == 1, "Compiler violates the standard");
Related
I have some code which needs to check if a bit in a bit field is set. I've been impressed with how optimized std::bitset.count compiles down, so thought this would be a good use of it as well. I'm surprised that when I use bitset.test, the compiler is still checking for exceptions, even when I add noexcept.
I have other checks to ensure that I won't test a bit which is out of range. Is there anything else I can do to optimize this code?
bool bitset_test(int n, size_t m) noexcept {
// The caller already verifies m is within range
return std::bitset<64>( n ).test( m );
}
Compiled output: https://godbolt.org/g/uRggXD
Is there anything else I can do to optimize this code?
Yes! Just like other containers, std::bitset has a function to get a specific bit with and without bounds checking. test is the bounds checking function, which throws.
But if you have other tests to make sure that m is not too high, then you can use std::bitset's operator[], which doesn't have any exception handling in the resulting assembly, because it assumes that you are passing a correct value:
bool bitset_test(int n, size_t m) noexcept {
return std::bitset<64>(n)[m];
}
As others have mentioned, the reason why the compiler still generates exceptions in the resulting assembly is because the compiler still has to call std::terminate if an exception is thrown, so it can't just ignore the exception.
Sometimes a local variable is used for the sole purpose of checking it in an assert(), like so -
int Result = Func();
assert( Result == 1 );
When compiling code in a Release build, assert()s are usually disabled, so this code may produce a warning about Result being set but never read.
A possible workaround is -
int Result = Func();
if ( Result == 1 )
{
assert( 0 );
}
But it requires too much typing, isn't easy on the eyes and causes the condition to be always checked (yes, the compiler may optimize the check away, but still).
I'm looking for an alternative way to express this assert() in a way that wouldn't cause the warning, but still be simple to use and avoid changing the semantics of assert().
(disabling the warning using a #pragma in this region of code isn't an option, and lowering warning levels to make it go away isn't an option either...).
We use a macro to specifically indicate when something is unused:
#define _unused(x) ((void)(x))
Then in your example, you'd have:
int Result = Func();
assert( Result == 1 );
_unused( Result ); // make production build happy
That way (a) the production build succeeds, and (b) it is obvious in the code that the variable is unused by design, not that it's just been forgotten about. This is especially helpful when parameters to a function are not used.
I wouldn't be able to give a better answer than this, that addresses that problem, and many more:
Stupid C++ Tricks: Adventures in assert
#ifdef NDEBUG
#define ASSERT(x) do { (void)sizeof(x);} while (0)
#else
#include <assert.h>
#define ASSERT(x) assert(x)
#endif
As of C++17, the variable can be decorated with an attribute.
[[maybe_unused]] int Result = Func();
assert( Result == 1 );
See https://en.cppreference.com/w/cpp/language/attributes/maybe_unused for details.
This is better than the (void)Result trick because you directly decorate the variable declaration, rather than add something as an afterthought.
You could create another macro that allows you to avoid using a temporary variable:
#ifndef NDEBUG
#define Verify(x) assert(x)
#else
#define Verify(x) ((void)(x))
#endif
// asserts that Func()==1 in debug mode, or calls Func() and ignores return
// value in release mode (any braindead compiler can optimize away the comparison
// whose result isn't used, and the cast to void suppresses the warning)
Verify(Func() == 1);
int Result = Func();
assert( Result == 1 );
This situation means that in release mode, you really want:
Func();
But Func is non-void, i.e. it returns a result, i.e. it is a query.
Presumably, besides returning a result, Func modifies something (otherwise, why bother calling it and not using its result?), i.e. it is a command.
By the command-query separation principle (1), Func shouldn't be a command and a query at the same time. In other words, queries shouldn't have side effects, and the "result" of commands should be represented by the available queries on the object's state.
Cloth c;
c.Wash(); // Wash is void
assert(c.IsClean());
Is better than
Cloth c;
bool is_clean = c.Wash(); // Wash returns a bool
assert(is_clean);
The former doesn't give you any warning of your kind, the latter does.
So, in short, my answer is: don't write code like this :)
Update (1): You asked for references about the Command-Query Separation Principle. Wikipedia is rather informative. I read about this design technique in Object Oriented Software Construction, 2nd Editon by Bertrand Meyer.
Update (2): j_random_hacker comments "OTOH, every "command" function f() that previously returned a value must now set some variable last_call_to_f_succeeded or similar". This is only true for functions that don't promise anything in their contract, i.e. functions that might "succeed" or not, or a similar concept. With Design by Contract, a relevant number of functions will have postconditions, so after "Empty()" the object will be "IsEmpty()", and after "Encode()" the message string will be "IsEncoded()", with no need to check. In the same way, and somewhat symetrically, you don't call a special function "IsXFeasible()" before each and every call to a procedure "X()"; because you usually know by design that you're fulfilling X's preconditions at the point of your call.
You could use:
Check( Func() == 1 );
And implement your Check( bool ) function as you want. It may either use assert, or throw a particular exception, write in a log file or to the console, have different implementations in debug and release, or a combination of all.
With C++17 we can do:
[[maybe_unused]] int Result = Func();
though it involves a bit of extra typing compared to a assert substitution. See this answer.
Note: Added this because is the first google hit for "c++ assert unused variable".
You should move the assert inside the function before the return value(s). You know that the return value is not an unreferenced local variable.
Plus it makes more sense to be inside the function anyway, because it creates a self contained unit that has its OWN pre- and post-conditions.
Chances are that if the function is returning a value, you should be doing some kind of error checking in release mode on this return value anyway. So it shouldn't be an unreferenced variable to begin with.
Edit, But in this case the post condition should be X (see comments):
I strongly disagree with this point, one should be able to determine the post condition from the input parameters and if it's a member function, any object state. If a global variable modifies the output of the function, then the function should be restructured.
Most answers suggest using static_cast<void>(expression) trick in Release builds to suppress the warning, but this is actually suboptimal if your intention is to make checks truly Debug-only. The goals of an assertion macro in question are:
Perform checks in Debug mode
Do nothing in Release mode
Emit no warnings in all cases
The problem is that void-cast approach fails to reach the second goal. While there is no warning, the expression that you've passed to your assertion macro will still be evaluated. If you, for example, just do a variable check, that is probably not a big deal. But what if you call some function in your assertion check like ASSERT(fetchSomeData() == data); (which is very common in my experience)? The fetchSomeData() function will still be called. It may be fast and simple or it may be not.
What you really need is not only warning suppression but perhaps more importantly - non-evaluation of the debug-only check expression. This can be achieved with a simple trick that I took from a specialized Assert library:
void myAssertion(bool checkSuccessful)
{
if (!checkSuccessful)
{
// debug break, log or what not
}
}
#define DONT_EVALUATE(expression) \
{ \
true ? static_cast<void>(0) : static_cast<void>((expression)); \
}
#ifdef DEBUG
# define ASSERT(expression) myAssertion((expression))
#else
# define ASSERT(expression) DONT_EVALUATE((expression))
#endif // DEBUG
int main()
{
int a = 0;
ASSERT(a == 1);
ASSERT(performAHeavyVerification());
return 0;
}
All the magic is in the DONT_EVALUATE macro. It is obvious that at least logically the evaluation of your expression is never needed inside of it. To strengthen that, the C++ standard guarantees that only one of the branches of conditional operator will be evaluated. Here is the quote:
5.16 Conditional operator [expr.cond]
logical-or-expression ? expression : assignment-expression
Conditional expressions group right-to-left. The first expression is
contextually converted to bool. It is evaluated and if it is true, the
result of the conditional expression is the value of the second
expression, otherwise that of the third expression. Only one of these
expressions is evaluated.
I have tested this approach in GCC 4.9.0, clang 3.8.0, VS2013 Update 4, VS2015 Update 4 with the most harsh warning levels. In all cases there are no warnings and the checking expression is never evaluated in Release build (in fact the whole thing is completely optimized away). Bare in mind though that with this approach you will get in trouble really fast if you put expressions that have side effects inside the assertion macro, though this is a very bad practice in the first place.
Also, I would expect that static analyzers may warn about "result of an expression is always constant" (or something like that) with this approach. I've tested for this with clang, VS2013, VS2015 static analysis tools and got no warnings of that kind.
The simplest thing is to only declare/assign those variables if the asserts will exist. The NDEBUG macro is specifically defined if asserts won't be effected (done that way round just because -DNDEBUG is a convenient way to disable debugging, I think), so this tweaked copy of #Jardel's answer should work (cf. comment by #AdamPeterson on that answer):
#ifndef NDEBUG
int Result =
#endif
Func();
assert(Result == 1);
or, if that doesn't suit your tastes, all sorts of variants are possible, e.g. this:
#ifndef NDEBUG
int Result = Func();
assert(Result == 1);
#else
Func();
#endif
In general with this stuff, be careful that there's never a possibility for different translation units to be build with different NDEBUG macro states -- especially re. asserts or other conditional content in public header files. The danger is that you, or users of your library might accidentally instantiate a different definition of an inline function from the one used inside the compiled part of the library, quietly violating the one definition rule and making the runtime behaviour undefined.
This is a bad use of assert, IMHO. Assert is not meant as an error reporting tool, it's meant to assert preconditions. If Result is not used elsewhere, it's not a precondition.
Certainly you use a macro to control your assert definition, such as "_ASSERT". So, you can do this:
#ifdef _ASSERT
int Result =
#endif /*_ASSERT */
Func();
assert(Result == 1);
int Result = Func();
assert( Result == 1 );
Result;
This will make the compiler stop complaining about Result not being used.
But you should think about using a version of assert that does something useful at run-time, like log descriptive errors to a file that can be retrieved from the production environment.
I'd use the following:
#ifdef _DEBUG
#define ASSERT(FUNC, CHECK) assert(FUNC == CHECK)
#else
#define ASSERT(FUNC, CHECK)
#endif
...
ASSERT(Func(), 1);
This way, for release build, the compiler don't even need to produce any code for assert.
If this code is inside a function, then act on and return the result:
bool bigPicture() {
//Check the results
bool success = 1 != Func();
assert(success == NO, "Bad times");
//Success is given, so...
actOnIt();
//and
return success;
}
// Value is always computed. We also call assert(value) if assertions are
// enabled. Value is discarded either way. You do not get a warning either
// way. This is useful when (a) a function has a side effect (b) the function
// returns true on success, and (c) failure seems unlikely, but we still want
// to check sometimes.
template < class T >
void assertTrue(T const &value)
{
assert(value);
}
template < class T >
void assertFalse(T const &value)
{
assert(!value);
}
I haven't succeeded in using [[maybe_unused]] but
you can use the unused attribute
int Result __attribute__((__unused__)) = Func();
gcc Variable-Attributes
I have this function for zero-overwriting things which uses static_assert to check if the given thing's type is a POD type:
template <bool safeMode = true, typename generic>
void overwriteWithZeros( generic *variableAddress )
{
if (safeMode) static_assert(std::is_pod<generic>::value, "Only POD types can be properly overwriten");
const size_t size = sizeof(generic);
unsigned char *variableData = (unsigned char*)(variableAddress);
for (size_t i = 0; i < size; i++)
variableData[i] = 0;
}
which I call here:
int main()
{
being *creature = new being(100, "a guinea pig"); // being is not a POD type
overwriteWithZeros<false>(creature);
// totally unrelated stuff...
}
And since safeMode is a compile time value, I don't know why it happens that being it true or being it false, static_assert always "happens", giving me the then expected error for being being not a POD type, as if this if before the static_assert simply wasn't there.
So, what am I doing wrong here?
Since you confirmed my suspicions (if itself is evaluated at run time despite of safeMode being a compile time value or not, while static_assert is evaluated at compile time), I changed the main question to:
What could I do to achieve what I'm trying here, so?
The problem is that static_assert is evaluated at compile time, this means that when the compiler finds it, then it evaluates it, regardless of where it is (unless it's excluded with a macro like #ifdef). To solve this problem you should make the enable flag part of the evaluation itself:
static_assert(!safeMode || std::is_pod<generic>::value, "Only POD types can be properly overwriten");
This is allowed because safeMode is a compile time value (being a template argument).
In both situations the static_assert will be evaluated but with safeMode == false it will always evaluate to true.
static_assert means exactly that, the assertion is done statically at compile time.
I'm in a position where this design would greatly improve the clarity and maintenance-needs for my code.
What I'm looking for is something like this:
#define MY_MACRO(arg) #if (arg)>0 cout<<((arg)*5.0)<<endl; #else cout<<((arg)/5.0)<<endl; #endif
The idea here:
The pre-processor substitutes different lines of code depending on the compile-time (constant) value of the macro argument. Of course, I know this syntax doesn't work, as the # is seen as the string-ize operator instead of the standard #if, but I think this demonstrates the pre-processor functionality I am trying to achieve.
I know that I could just put a standard if statement in there, and the compiler/runtime would be left to check the value. But this is unnecessary work for the application when arg will always be passed a constant value, like 10.8 or -12.5 that only needs to be evaluated at compile-time.
Performance needs for this number-crunching application require that all unnecessary runtime conditions be eliminated whenever possible, and many constant values and macros have been used (in place of variables and functions) to make this happen. The ability to continue this trend without having to mix pre-processor code with real if conditions would make this much cleaner - and, of course, code-cleanliness is one of the biggest concerns when using macros, especially at this level.
As far as I know, you cannot have #if (or anything similar) inside your macro.
However, if the condition is known at compile-time, you can safetly use a normal if statement. The compiler will optimise it (assuming you have optimisions turned on).
It's called "Dead code elimination"
Simple, use real C++:
template <bool B> void foo_impl (int arg) { cout << arg*5.0 << endl; }
template < > void foo_impl<false>(int arg) { cout << arg/5.0 << endl; }
template <int I> void foo ( ) { foo_impl< (I>0) >(I); }
[edit]
Or in modern C++, if constexpr.
Could you give an example where static_assert(...) ('C++11') would solve the problem in hand elegantly?
I am familiar with run-time assert(...). When should I prefer static_assert(...) over regular assert(...)?
Also, in boost there is something called BOOST_STATIC_ASSERT, is it the same as static_assert(...)?
Static assert is used to make assertions at compile time. When the static assertion fails, the program simply doesn't compile. This is useful in different situations, like, for example, if you implement some functionality by code that critically depends on unsigned int object having exactly 32 bits. You can put a static assert like this
static_assert(sizeof(unsigned int) * CHAR_BIT == 32);
in your code. On another platform, with differently sized unsigned int type the compilation will fail, thus drawing attention of the developer to the problematic portion of the code and advising them to re-implement or re-inspect it.
For another example, you might want to pass some integral value as a void * pointer to a function (a hack, but useful at times) and you want to make sure that the integral value will fit into the pointer
int i;
static_assert(sizeof(void *) >= sizeof i);
foo((void *) i);
You might want to asset that char type is signed
static_assert(CHAR_MIN < 0);
or that integral division with negative values rounds towards zero
static_assert(-5 / 2 == -2);
And so on.
Run-time assertions in many cases can be used instead of static assertions, but run-time assertions only work at run-time and only when control passes over the assertion. For this reason a failing run-time assertion may lay dormant, undetected for extended periods of time.
Of course, the expression in static assertion has to be a compile-time constant. It can't be a run-time value. For run-time values you have no other choice but use the ordinary assert.
Off the top of my head...
#include "SomeLibrary.h"
static_assert(SomeLibrary::Version > 2,
"Old versions of SomeLibrary are missing the foo functionality. Cannot proceed!");
class UsingSomeLibrary {
// ...
};
Assuming that SomeLibrary::Version is declared as a static const, rather than being #defined (as one would expect in a C++ library).
Contrast with having to actually compile SomeLibrary and your code, link everything, and run the executable only then to find out that you spent 30 minutes compiling an incompatible version of SomeLibrary.
#Arak, in response to your comment: yes, you can have static_assert just sitting out wherever, from the look of it:
class Foo
{
public:
static const int bar = 3;
};
static_assert(Foo::bar > 4, "Foo::bar is too small :(");
int main()
{
return Foo::bar;
}
$ g++ --std=c++0x a.cpp
a.cpp:7: error: static assertion failed: "Foo::bar is too small :("
I use it to ensure my assumptions about compiler behaviour, headers, libs and even my own code are correct. For example here I verify that the struct has been correctly packed to the expected size.
struct LogicalBlockAddress
{
#pragma pack(push, 1)
Uint32 logicalBlockNumber;
Uint16 partitionReferenceNumber;
#pragma pack(pop)
};
BOOST_STATIC_ASSERT(sizeof(LogicalBlockAddress) == 6);
In a class wrapping stdio.h's fseek(), I have taken some shortcuts with enum Origin and check that those shortcuts align with the constants defined by stdio.h
uint64_t BasicFile::seek(int64_t offset, enum Origin origin)
{
BOOST_STATIC_ASSERT(SEEK_SET == Origin::SET);
You should prefer static_assert over assert when the behaviour is defined at compile time, and not at runtime, such as the examples I've given above. An example where this is not the case would include parameter and return code checking.
BOOST_STATIC_ASSERT is a pre-C++0x macro that generates illegal code if the condition is not satisfied. The intentions are the same, albeit static_assert is standardised and may provide better compiler diagnostics.
BOOST_STATIC_ASSERT is a cross platform wrapper for static_assert functionality.
Currently I am using static_assert in order to enforce "Concepts" on a class.
example:
template <typename T, typename U>
struct Type
{
BOOST_STATIC_ASSERT(boost::is_base_of<T, Interface>::value);
BOOST_STATIC_ASSERT(std::numeric_limits<U>::is_integer);
/* ... more code ... */
};
This will cause a compile time error if any of the above conditions are not met.
One use of static_assert might be to ensure that a structure (that is an interface with the outside world, such as a network or file) is exactly the size that you expect. This would catch cases where somebody adds or modifies a member from the structure without realising the consequences. The static_assert would pick it up and alert the user.
In absence of concepts one can use static_assert for simple and readable compile-time type checking, for example, in templates:
template <class T>
void MyFunc(T value)
{
static_assert(std::is_base_of<MyBase, T>::value,
"T must be derived from MyBase");
// ...
}
This doesn't directly answers the original question, but makes an interesting study into how to enforce these compile time checks prior to C++11.
Chapter 2 (Section 2.1) of Modern C++ Design by Andrei Alexanderscu implements this idea of Compile-time assertions like this
template<int> struct CompileTimeError;
template<> struct CompileTimeError<true> {};
#define STATIC_CHECK(expr, msg) \
{ CompileTimeError<((expr) != 0)> ERROR_##msg; (void)ERROR_##msg; }
Compare the macro STATIC_CHECK() and static_assert()
STATIC_CHECK(0, COMPILATION_FAILED);
static_assert(0, "compilation failed");
To add on to all the other answers, it can also be useful when using non-type template parameters.
Consider the following example.
Let's say you want to define some kind of function whose particular functionality can be somewhat determined at compile time, such as a trivial function below, which returns a random integer in the range determined at compile time. You want to check, however, that the minimum value in the range is less than the maximum value.
Without static_assert, you could do something like this:
#include <iostream>
#include <random>
template <int min, int max>
int get_number() {
if constexpr (min >= max) {
throw std::invalid_argument("Min. val. must be less than max. val.\n");
}
srand(time(nullptr));
static std::uniform_int_distribution<int> dist{min, max};
std::mt19937 mt{(unsigned int) rand()};
return dist(mt);
}
If min < max, all is fine and the if constexpr branch gets rejected at compile time. However, if min >= max, the program still compiles, but now you have a function that, when called, will throw an exception with 100% certainty. Thus, in the latter case, even though the "error" (of min being greater than or equal to max) was present at compile-time, it will only be discovered at run-time.
This is where static_assert comes in.
Since static_assert is evaluated at compile-time, if the boolean constant expression it is testing is evaluated to be false, a compile-time error will be generated, and the program will not compile.
Thus, the above function can be improved as so:
#include <iostream>
#include <random>
template <int min, int max>
int get_number() {
static_assert(min < max, "Min. value must be less than max. value.\n");
srand(time(nullptr));
static std::uniform_int_distribution<int> dist{min, max};
std::mt19937 mt{(unsigned int) rand()};
return dist(mt);
}
Now, if the function template is instantiated with a value for min that is equal to or greater than max, then static_assert will evaluate its boolean constant expression to be false, and will throw a compile-time error, thus alerting you to the error immediately, without giving the opportunity for an exception at runtime.
(Note: the above method is just an example and should not be used for generating random numbers, as repeated calls in quick succession to the function will generate the same numbers due to the seed value passed to the std::mt19937 constructor through rand() being the same (due to time(nullptr) returning the same value) - also, the range of values generated by std::uniform_int_distribution is actually a closed interval, so the same value can be passed to its constructor for upper and lower bounds (though there wouldn't be any point))
The static_assert can be used to forbid the use of the delete keyword this way:
#define delete static_assert(0, "The keyword \"delete\" is forbidden.");
Every modern C++ developer may want to do that if he or she wants to use a conservative garbage collector by using only classes and structs that overload the operator new to invoke a function that allocates memory on the conservative heap of the conservative garbage collector that can be initialized and instantiated by invoking some function that does this in the beginning of the main function.
For example every modern C++ developer that wants to use the Boehm-Demers-Weiser conservative garbage collector will in the beginning of the main function write:
GC_init();
And in every class and struct overload the operator new this way:
void* operator new(size_t size)
{
return GC_malloc(size);
}
And now that the operator delete is not needed anymore, because the Boehm-Demers-Weiser conservative garbage collector is responsible to both free and deallocate every block of memory when it is not needed anymore, the developer wants to forbid the delete keyword.
One way is overloading the delete operator this way:
void operator delete(void* ptr)
{
assert(0);
}
But this is not recommended, because the modern C++ developer will know that he/she mistakenly invoked the delete operator on run time, but this is better to know this soon on compile time.
So the best solution to this scenario in my opinion is to use the static_assert as shown in the beginning of this answer.
Of course that this can also be done with BOOST_STATIC_ASSERT, but I think that static_assert is better and should be preferred more always.