renatogarcia / icecream-cpp Goto Github PK
View Code? Open in Web Editor NEW๐ฆ Never use cout/printf to debug again
License: Other
๐ฆ Never use cout/printf to debug again
License: Other
Some functionalities in <codecvt>
(e.g. std::codecvt<char16_t, char, std::mbstate_t>
) are being deprecated since C++ 17/20. Please refer to https://en.cppreference.com/w/cpp/locale/codecvt for more details. Compiling with these usages may throw annoying warnings.
Just to share my experience, hope it will help someone, great and useful lib, so here it is ...
Testbed :
Debian clang version 16.0.6 (15)
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
Icecream : from master
Add #include <cstdarg>
in icecream.hpp in order to avoid these following errors caused by this statement in mytest.cxx
using icecream::f_;
In file included from mytest.cxx:8:
./icecream.hpp:1613:58: error: unexpected type name 'T0': expected expression
result.push_back(static_cast<T>(va_arg(args, T0)));
^
./icecream.hpp:1628:38: error: expected '(' for function-style cast or type construction
auto v = va_arg(args, int) & 0x01;
~~~^
./icecream.hpp:1647:43: error: expected '(' for function-style cast or type construction
double d = va_arg(args, double);
~~~~~~^
./icecream.hpp:1674:41: error: unexpected type name 'T0': expected expression
return Tree{(T)(T1)va_arg(args, T0), std::move(buf_)};
^
./icecream.hpp:1680:34: error: expected '(' for function-style cast or type construction
auto i = va_arg(args, int) & 0x01;
~~~^
./icecream.hpp:1694:37: error: expected '(' for function-style cast or type construction
auto d = va_arg(args, double);
~~~~~~^
./icecream.hpp:1873:9: error: use of undeclared identifier 'va_start'
va_start(args, format);
^
./icecream.hpp:1926:9: error: use of undeclared identifier 'va_end'
va_end(args);
GCC is more permissive and seems to ignore this ...
gcc (Debian 13.2.0-4) 13.2.0
#define ICECREAM_UNPACK_30(F, ICM, ...) ICECREAM_UNPACK_29(F, ICM, __VA_ARGS__), std::get<39>(std::move(ret_tuple))
Is this supposed to be get< 39 > ?
std::string str = "ABCDE";
std::string_view sub{str.data() + 1, 3};
IC(sub);
// expected: ic| sub: "BCD"
// actual: ic| sub: "BCDE"
(see https://godbolt.org/z/b3a9Eq)
I think line 703
buf << '"' << cv.to_bytes(value.data()) << '"';
should be
buf << '"' << cv.to_bytes(value.data(), value.data() + value.size()) << '"';
and maybe the Microsoft-specific code a few lines above has to be adjusted, too.
But I don't know icecream-cpp well enough to be sure.
Just creating a git tag, and changing the version number in CMakeLists.txt would be good.
The last release was 2 years ago, while there has been a bunch of new stuff added!
I'm used to the Python icecream library and really like this style of printf based debugging.
While looking for C++ based library, I found this repo & another one: https://github.com/sharkdp/dbg-macro
Are you aware of it? Any comparison between the two? which features one supports & the other doesn't etc?
What is the simplest way to print function called with the arguments that were passed? I'm debugging an interface implementation, so I don't have so much control over who is calling me methods; rather I am on the receiving end of them being called.
I can add IC()
at the beginning of a function to see its name and arguments, but the argument values themselves aren't printed.
C++20 has the std::source_location which replaces the need for macros.
Hi, I try to use the header file, but it reported a build error.
I see that in some of my header file, the _()
is defined to text translation. (For example, under wxWidgets, the _()
is defined as:
#define _(s) wxGetTranslation((s))
While, I see in the icecream.hpp, it also define some function like:
template<typename... Ts>
auto _(std::string const& fmt, Ts&&... vs) -> detail::FormatterPack<decltype(std::forward<Ts>(vs))...>
{
return detail::FormatterPack<decltype(std::forward<Ts>(vs))...>{fmt, std::forward<Ts>(vs)...};
}
So, I would like to find a way to solve such conflict issue. Thanks.
Due to limited information provided by Clang when using __builtin_dump_struct
function, some struct members types can not be printed. Enums, none of them can be printed. With arrays, only the ones with elements of fundamental types, fixed width integers, std::size_t
, std::ptrdiff_t
, and any pointer, declared using canonical names (i.e.: not type aliases), can be printed.
When using the __builtin_dump_struct
function, both enums and arrays are dumped to some_printf_func
using the %p
specifier, regardless of its elements type. With only that information would not be possible recover and print neither the enum values nor any array element.
However, preceding each call to some_printf_func
with a %p
specifier by __builtin_dump_struct
, a call to that same function will be done having as argument a string with the member signature (type and name). To enums that is not of any help, but to arrays, inspecting that string is possible deduce the array size and its elements types.
Knowing that information, an array dumped with a preceding "short [50] bla" string can be deduced as being an array of 50 short int
. That works identically for any fundamental type, but is not possible infer the array elements type if an alias is used. With the code:
using Integer = int;
struct Point
{
double x;
double y;
};
struct S
{
Integer integers[10];
Point coords[5];
};
there is no way to know what fundamental type Integer
is an alias to, neither what are the internal members of Point
struct. Consequently, both integers
and coords
members can not be printed.
To enums, its values are represented using an integral type defined at enum declaration, like:
enum EN : std::uint64_t
{
UM,
DOIS,
TRES
};
However, inside of some_printf_func
it's not possible to get that information. Therefore, not kowning the bit size of each enum value it's not possible print them.
Is there a way to print a simple string literal? Using
IC("test")
causes a SIGSEGV.
Due to a Clang bug, is not possible correctly print float and double struct members declared using aliased type names.
When calling variadic functions, float arguments are promoted to doubles before being passed. However, the Clang float promotion before the calling of some_printf_func
, given as argument of __builtin_dump_struct
, is buggy. It seems like instead of converting it to a double with the same numeric value, the float 32 bits are just copied to the first 32 bits of a double.
As a consequence of that behavior, inside of some_printf_func
, if you know that your next %f
specified variadic argument is a double
, you can just do va_arg(args, double)
as usual. On other hand, if you know that your next argument is a float
, you can do double d = va_arg(args, double)
and reinterpret the first 32 bits with *((float*)&d)
. However, if you don't know if your argument is either a double
or a float
, it won't be possible decide between interpret the whole 64 bits as a double
or the first 32 bits as a float
.
When using the __builtin_dump_struct
function, a %f
specifier will be used to both float
and double
arguments indistinctly. Luckily, preceding each call to some_printf_func
with a %
specifier, a call to that same function will be done having as argument a string with the variable signature (type and name). So, inspecting that string would be possible deduce the variable type before its promotions to a double
. The %f
argument with a "const float foo" string must be a float
, and with a "double bar" must be a double
.
However, if the %f
argument has been declared with an aliased type name, its inference as float
or double
is not possible. With the code:
using MyNumber = float;
struct S
{
MyNumber num;
};
, when dumping the struct S
, the information of num
variable being either float
or double
is lost. The IceCream-cpp approach is presume num
as a double
, but print its value alongside a warning.
Summarizing, float
and double
struct members declared with canonical names will work just fine. If a name alias is used, on IceCream-cpp side is not possible distinguish between them, and a double
type is presumed. If num
is a double
the printed value is correct, if it is a float
the printed value is wrong.
On Clang 8+, __builtin_dump_struct pretty prints a struct variable without any manual boilerplate.
See https://stackoverflow.com/a/58721823/4140668
I was using version 0.1.0 of icecream-cpp for a while, and I have IC
statements in multiple source files, which are compiled independently (as cmake object libraries) and then linked together into different binaries and shared libraries. This used to work very nicely. Now I upgraded to 0.3.0, recompiled everything, and get linking errors like so:
multiple definition of `icecream::detail::show_c_string()'
I know that this is potentially an issue with header only libraries in general, but perhaps there is something you can do, as it used to work in previous versions.
#include <algorithm>
#include <numeric>
#include "icecream.hpp"
using namespace std;
#define DETECT_TYPE(x) \
do \
{ \
IC(sizeof(x)); \
IC_("d", std::numeric_limits<x>::max()); \
IC_("d", std::numeric_limits<x>::min()); \
IC_("d", std::numeric_limits<x>::lowest()); \
} while (0)
int main(int argc, char **argv)
{
DETECT_TYPE(char);
DETECT_TYPE(unsigned char);
return 0;
}
expect: it should display max: 128, min: -127, lowest: -127
gcc 11.2 linux
I'm trying to print an instance of a user-defined class as follows.
class MyStruct {
public:
int i;
double d;
std::string s;
std::vector<int> v;
};
MyStruct x;
x.i = 2; x.d = 0.9; x.s = std::string("abc"); x.v = {1, 2, 3}; // set member variables
IC(x);
What I expected was something like
ic| x: {i: 2, d: 0.9, s: "abc", v: [1, 2, 3]}
but what I actually got was the following.
ic| x: {i: 2, d: 0.9, s: {__r_: {}}, v: {}}
It seems that a member variable is not properly displayed when it is an STL container. If I print each member IC(x.s, x.v)
, I got the correct output. Could someone investigate this issue?
FYI, my compiler is Apple clang version 11.0.0 (clang-1100.0.33.17).
The code
char const foo[] = "bar";
IC((char*)foo);
Should print
ic| (char*)foo: "bar"
But now is printing
ic| char*: "bar"
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.