Sorry this seems like a noddy question but how do you get the compiler to generate a warning when a certain variable / structure is used?
For example if I have the following code:
int GetAbstractedFoo()
{
return 1;
}
struct new_name
{
int foo;
}
typedef new_name old_name;
How do i do a #warning to say "warning "old_name" is depreciated please use new_name"
and expanding on that further how could is say "warning accessing foo directly has been depreciated please use "abstractedFoo"?
I have had trouble googling this beyond the basic #warning when a header is used.
-Thanks, Chris
Ah so a bit more digging and I came across this post and the fab answer by Michael Platings:
C++ mark as deprecated
I think for my purposes I shall extend the macro to:
#define DEPRECATE( var , explanation ) var __attribute__((availability(myFramework,introduced=1,deprecated=2.1,obsoleted=3.0, message= explanation)));
DEPRECATE ( typedef old_name new_name, “please use new_name”);
Related
This isn't a specific question about a language, but more about programming in general. The question came after I started an argument with a friend about "Function prototypes" which I learnt about recently from my C++ course. I mentioned to him that prototypes are function headers that you have to create at the beginning of your code so the compiler allocates some space at runtime before getting to the actual function. We then started rambling about whether other programming languages (Like java or python) which do not utilize function prototypes -- so far as we're concerned -- actually had a system similar to that of C++, just that they handled it themselves rather than having the user create them.
So we're curious to know, what are function prototypes after all? Are they only accountable on C/C++, or do other programming languages make use of them? And is it something I'd need to develop more on as a future programmer? Thanks for the help!
With respect to C and C++, the word "prototype" refers to a specific declaration syntax.
In the earliest versions of C, function definitions were written as
int func( arg1, arg2, arg3 ) // no types in argument list, just identifiers
int arg1;
double arg2;
char *arg3;
{
// function body
}
and declarations were written as
int func( ); // no argument list
The function argument list only contained identifiers and no type information - that was supplied separately. Function declarations didn't include arguments, just the return type.
C++ introduced and C later adopted the concept of prototype syntax, where the type information is included in the parameter list in both the definition:
int func( int arg1, double arg2, char *arg3 )
{
// function body
}
and the declaration
int func( int, double, char * );
This allowed compilers to check the number and types of arguments in a function call and issue diagnostics if they didn't match, rather than waiting until runtime to find out if there's a problem.
While the old-style function declaration and definition syntax is still supported, it should not be used for new code development - we're almost to the point where the word "prototype" is kind of redundant, since prototype syntax is the norm rather than the exception.
Statically-typed languages like Fortran and Pascal and Ada all have separate function declarations, but they don't refer to those declarations as prototypes. And again with C, "prototype" refers to a specific style of function declaration and definition, not just a declaration in and of itself.
This is greatly oversimplified, but the reason for function prototypes is "one-pass compilers."
If your compiler only makes one pass through the code, it needs to know what functions are available to it, before the function implementation is called. This is where prototypes come in.
Compilers that make multiple passes through the code build jump tables that tell it where all the functions are, so there's no need for function prototypes.
In C compilers, prototypes are used to check the type and number of function parameters (i.e. the function signature). This program:
#include <stdio.h>
int main()
{
printf("%d\n",add(3));
}
int add(int i, int j)
{
return i+j;
}
compiles and executes in Clang 7 with a warning, even though the result is meaningless (i.e. undefined behavior).
Whereas this program, incorporating a function prototype:
#include <stdio.h>
int add (int, int); /* function prototype for add */
void main()
{
printf("%d\n",add(3));
}
int add(int i, int j)
{
return i+j;
}
fails to compile.
C and C++ are compiled to native code and support calling between compilation units (files). To call a function XYZ from a neighboring compilation unit the compiler inserts a reference "calling XYZ" which is later resolved by the linker. But you need to know what to prepare on the stack for the function. The prototype supplies that information without having to compile the whole function.
Early C treated everything as int and as the C calling convention is caller-cleans-up, you as the caller know how many ints to remove from the stack after a function returns. If you call printf with three arguments without explaining what it is, the C compiler can still figure out what code to generate. If you misspelled it to vrintf it will compile but fail to link. So plain C worked (still works?) to some extent without prototypes (or treats missing prototypes as just a warning).
As C++ can pass all kinds of crazy stuff as function arguments, if you try to call something without explaining its argument types first, the compiler does not know what code to generate and you get an error.
This outside article is reasonably nice: http://www.cplusplus.com/articles/yAqpX9L8/
I created a multi-index container with 3 non-unique, non-ordered keys looking like following:
namespace bmi = boost::multi_index;
class SurveyRepository {
// some other code
using SurveyCodeContainer = boost::multi_index_container<
SurveyCode,
bmi::indexed_by<
bmi::hashed_non_unique<bmi::tag<Survey>, bmi::member<SurveyCode, unsigned, &SurveyCode::survey_id>>,
bmi::hashed_non_unique<bmi::tag<Table>, bmi::member<SurveyCode, unsigned, &SurveyCode::table_id>>,
bmi::hashed_non_unique<bmi::tag<Check>, bmi::member<SurveyCode, unsigned, &SurveyCode::check_id>>
>
>;
SurveyCodeContainer m_SurveyCodeContainer;
};
The point was to be able to search the SurveyCode objects using any of those keys and I thought it's totally readable and quite a neat solution.
But there was a code review and although the multi_index_container has been already used in our code base in the past, some people have been confused with comments like:
Isnt there a less ugly container?
So is there a way how to make it less ugly/more readable? We are using Visual Studio 2019 and I would prefer some solution from stl instead of boost, but I guess there isn't any, right?
If you're using C++17, there's a slightly more convenient syntax available:
namespace bmi = boost::multi_index;
class SurveyRepository {
// some other code
using SurveyCodeContainer = boost::multi_index_container<
SurveyCode,
bmi::indexed_by<
bmi::hashed_non_unique<bmi::tag<Survey>, bmi::key<&SurveyCode::survey_id>>,
bmi::hashed_non_unique<bmi::tag<Table>, bmi::key<&SurveyCode::table_id>>,
bmi::hashed_non_unique<bmi::tag<Check>, bmi::key<&SurveyCode::check_id>>
>
>;
SurveyCodeContainer m_SurveyCodeContainer;
};
So I'm trying to do an assignment for an ml course, the issue is that the function requires a set type: int * int -> int for example, and the way that I see to solve the problem is to use another function (say for iteration) to solve the problem.
I believe that lisp has some kind of way of having a function be in scope for only one other function.
I think that this could be done:
fun a (x, y) =
let
fun b (i,j) = ...;
in
...;
[Not sure of exact syntax for this but I remember reading something like this only it was for temporary variables (which could be functions?]
but please correct me if this is wrong.
In ML, functions are first class citizens (i.e. values). You can bind them via let just like any other value.
Therefore, your idea is correct. It is especially a good design for functions passed as "iterators" (i.e. to map/fold/iter). Your question is too vague however for any further advise.
Since SWIG can't parse the __attribute__((packed)) on some C structs I'd like to wrap, I work around this by putting a
#define __attribute__(x)
in my .i file.
When will this come and bite me?
This is actually perfectly sane. SWIG doesn't need to know anything about the layout of the structs you're wrapping in order to be able to generate correct code. (It doesn't even need to know about all the members they contain even).
The reason for this is that the code which is generated is largely just marshaling data. In C you can legally write:
void show_a(const struct foo *instance) {
printf("%s", instance->b);
}
Regardless of whether foo was defined as:
struct foo {
double a;
char *b;
}
or
struct foo {
char *b;
double a,c;
int xyz;
}
The only place where the packing/alignment matters is when creating new structs. This is handled correctly though also, provided you don't also hide the attribute from the C compiler itself, because the generated C wrapper code will be using the real definition and not the pseudo one that you showed in the interface file.
It's a little bit clunky, but you can convince yourself of this as required by reading through the generated wrapper.
The general answer is that you can lie to SWIG itself quite a lot and it'll all work out alright in the end when the C compiler sees the generated code and reconciles it with the real definitions/declarations.
In the specific case the short answer is: so long as you only put that #define in the .i file and then only in a place where it doesn't get passed out to your generated module_wrap.c you're fine.
In case of lack of proper updated tutorials for some particular library functions (in my case, latest allegro5), how can one learn by oneself how to call and use those functions? Is there some clue in header files?
thanks in advance
The header files are going to provide you with the bare minimum information required to correctly compile a program with those functions. It has the types, constants, and function prototypes. Nothing (short of comments) is going to explain how to correctly use the functions, just how to call them.
General
For example, if you see:
int do_something(int n, const char* desc);
You can only infer that you need to pass an integer n and a (C) string desc. That function returns an integer as well.
For a more complex example:
typedef struct {
int foo;
double bar;
} blam_t;
void munge(blam_t info);
You know that munge takes one argument of type blam_t which is a custom structure, as defined above. You could use that to create a blam_t variable and pass it to munge():
blam_t myvar;
myvar.foo = 42;
myvar.bar = 0.67;
munge(myar);
Allegro5
If we look at the source of include/allegro5/display.h we see things like this:
AL_FUNC(void, al_set_new_display_flags, (int flags));
This is an uncommon way of defining functions. They are using a macro AL_FUNC to define their functions. We see (by clicking on it) that AL_FUNC is defined as:
#define AL_FUNC(type, name, args) type name args
So that first example basically becomes:
void al_set_new_display_flags(int flags);
And we can call it with just an integer argument.
Without any documentation, you can only hope to learn by trying the functions. Then this becomes more a reverse engineering task.