Earlier quoted context omitted.
I also want to remove CROW_ROUTE, but with the current c++ standard, it cannot be avoided. To check whether handler is valid with given URL at compile time, `url' (string literal) argument requires in compile time and in run time. const char* value is invalid for template argument and argument of non-constexpr function cannot be constexpr value. Thus I used macro to provied `url' argument twice; in template argument…
You can still do metaprogramming on single character constants and with a bunch of really ugly hackery make it somewhat pretty. You might be interested in metaparse [1] which can greatly simplify compile time parsing of strings but has a very steep learning curve. [1]: http://abel.web.elte.hu/mpllibs/metaparse/
Crow – C++ Microframework for Web, inspired by Python Flask
31–40 of 65 posts
Re: Crow – C++ Microframework for Web, inspired by Python Flask
#32Earlier quoted context omitted.
> because all the code becomes inline. The language says that's just a suggestion to the compiler, right? Does any compiler actually inline for non-trivial methods?
`inline` has a different meaning in C++. The compiler is free to inline the call if it wishes to, but `inline` means that the same function can be defined in multiple translation units without breaking the one definition rule. Example: // header.hpp inline int f(int x) { return x + 1; } // a.cpp #include "header.hpp" // b.cpp #include "header.hpp" If f was not marked inline, linking a.cpp and b.cpp together would fin…
'inline' in C is a hint to the compiler that you'd like the function inlined.
You can combine the two, and, in fact, it seems like a good idea IME to also use static if you're using inline.
Are you sure c++ is that different?
Re: Crow – C++ Microframework for Web, inspired by Python Flask
#33 CROW_ROUTE(app, "/about")
([](Response res){
res.send("About Crow example");
});
Why you might ask? So you can do this: CROW_ROUTE(app, "/about")
([](Response res){
responses.push_back(res);
});
And then some independent method could come along and do the res.send() when it is ready. The connection would hang until res.send() or similar is called on it. There would also be methods on the Response object so you can see if the connection is still alive etc, and maybe the ability to set timeouts directly on the Response object.[edit] This would allow people using your framework to implement long polling without locking up an io_service thread for each connection. It would also make it easier to add support for web sockets etc at a later date.
[edit2] This is how NodeJS works. Both a request and a response object is passed to the callback, then you can do for example:
function callback (req, res) {
setTimeout(function(){
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello World\n');
}, 5000);
}Re: Crow – C++ Microframework for Web, inspired by Python Flask
#34Earlier quoted context omitted.
You can still do metaprogramming on single character constants and with a bunch of really ugly hackery make it somewhat pretty. You might be interested in metaparse [1] which can greatly simplify compile time parsing of strings but has a very steep learning curve. [1]: http://abel.web.elte.hu/mpllibs/metaparse/
I already considered using a template with single character constants, and I thought the technic didn't have much benefit over the macro version. Maybe compile-time routing function genetation could be possible with it (and would faster), but requres HUGE work I think. I will try and benchmark it later.
Useful strings at compile time is a desirable feature beyond c++, though. A perfect hash could be a nice solution, I thought, but I got around to trying out gperf, and it was much slower than I expected. Probably too slow to use in ordinary situations. I guess gperf is for when (runtime) performance is incredibly important.
Another possible approach to strings at compile time is something like flex, or re2c. I haven't tested them in this type of scenario. But, apparently Zed Shaw used ragel to parse http in Mongrel to excellent effect. My problem with ragel is its complicated syntax.
Re: Crow – C++ Microframework for Web, inspired by Python Flask
#35Earlier quoted context omitted.
`inline` has a different meaning in C++. The compiler is free to inline the call if it wishes to, but `inline` means that the same function can be defined in multiple translation units without breaking the one definition rule. Example: // header.hpp inline int f(int x) { return x + 1; } // a.cpp #include "header.hpp" // b.cpp #include "header.hpp" If f was not marked inline, linking a.cpp and b.cpp together would fin…
What you are describing sounds a lot like 'static' in C, which marks a function to not export its name, so it can't be seen from outside the file. 'inline' in C is a hint to the compiler that you'd like the function inlined. You can combine the two, and, in fact, it seems like a good idea IME to also use static if you're using inline. Are you sure c++ is that different?
`inline` is used extensively in C++ to make header-only libraries possible; otherwise you'd get constant symbol clashes during linking. With `static` you would get enormous size blowup. It has little to do with the actual inlining of the call, which is mostly up to the compiler.
In C, the situation is complicated. `inline` does not exist in C89. GCC has an interpretation of it for C89 (-std=gnu89), which differs from the C99 interpretation. The only safe way to use inline in C is usually to couple it with `static`, unless you know what you're doing. The C99 interpretation of inline is similar to C++, but once again not exactly. For example:
// header.h
// int f(int x);
inline int f(int x) { return x + 1; }
// a.h
int a(int x);
// a.c
#include "header.h"
#include "a.h"
int a(int x) { return f(x); }
// b.h
int b(int x);
// b.c
#include "header.h"
#include "b.h"
int b(int x) { return f(x); }
// main.c
#include "a.h"
#include "b.h"
int main(int argc, char **argv) {
return a(argc) + b(argc);
}
This is code that compiles perfectly fine in C++, but is invalid C, because when the compiler decides not to inline the calls to f, it has no linkage of its own. But when one declares f to have linkage (by uncommenting that line in header.h), we now get 'multiple definition' errors.Re: Crow – C++ Microframework for Web, inspired by Python Flask
#36Re: Crow – C++ Microframework for Web, inspired by Python Flask
#37Re: Crow – C++ Microframework for Web, inspired by Python Flask
#38Earlier quoted context omitted.
What you are describing sounds a lot like 'static' in C, which marks a function to not export its name, so it can't be seen from outside the file. 'inline' in C is a hint to the compiler that you'd like the function inlined. You can combine the two, and, in fact, it seems like a good idea IME to also use static if you're using inline. Are you sure c++ is that different?
`static` will result in a copy of f for every translation unit (without LTO, at least). `inline` will not. `static inline` is effectively the same as `static`, with a slight hint to the compiler to inline the call. `inline` is used extensively in C++ to make header-only libraries possible; otherwise you'd get constant symbol clashes during linking. With `static` you would get enormous size blowup. It has little to do…
It sounds like you've confirmed my intuition about inline in C, and I find inline to be only marginally-useful at best. inline functions are syntactically-prettier than macros, but they lose the other major benefit of macros, which is increased flexibility about typing and being able to interact with syntax in ways that functions can't. I get the impression that inline probably didn't need to be included in the standard, or, at least, somehow they blew the opportunity to add something more useful.
C's situation still seems less complicated than C++'s. I can't grasp exactly what C++ 'inline' actually tells the compiler to do, based on your description. It sounds like 'inline' in C++ is just a smarter 'static'. Why can't those smarts be implanted into 'static'?
Re: Crow – C++ Microframework for Web, inspired by Python Flask
#39I like the technique to generate compile error when there is a mismatch between format string and actual argument list and type - This is what only statically typed language can do and dynamically typed languages like python can't do. Maybe this technique could be applied in printf or other C++ APIs using format string.
Not sure if you're being ironic, but you're describing e.g. GCC's "format" function attribute ( https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html#... ), it makes the compiler verify the arguments for printf() and other format-string functions. It's not new, it has been in GCC for quite a number of years (not sure how to check this quickly). UPDATE : I found a list ( https://ohse.de/uwe/articles/gcc-attribut…
Re: Crow – C++ Microframework for Web, inspired by Python Flask
#40I like the technique to generate compile error when there is a mismatch between format string and actual argument list and type - This is what only statically typed language can do and dynamically typed languages like python can't do. Maybe this technique could be applied in printf or other C++ APIs using format string.