Coder Social home page Coder Social logo

Comments (12)

tfc avatar tfc commented on June 11, 2024 1

It seems like it would be quite helping in your case if your printf-implementation would recognize "callable" arguments. It could then call them when they are needed and they serialize themselves into a buffer (and they all could use the same one), or something like that. But that is on a layer that is completely off from where pprintpp works... I see that it's tempting to do something in pprintpp, but it's hard to see where this would really fit when thinking this through.

from pprintpp.

DBJDBJ avatar DBJDBJ commented on June 11, 2024

Well, there is this ancient school of philosophy that claims: "nothing must break encapsulation and decoupling" ...

  pprint(" Hey Ma, Look: { %foo } !", _foo_instance ) ;

They go as far as claiming above "integration" naturally breaks both in one go, for the foo type... I might be sure they would advise on this course of action:

   pprint("Hey, Ma, look: { }!",   foo::to_string( _foo_instance ) ) ;

Complete decoupling and complete encapsulation ... Silly people ...

from pprintpp.

TorstenRobitzki avatar TorstenRobitzki commented on June 11, 2024

Well, this requires some kind of std::string. Being in the embedded world, providing a statically allocated buffer, that can be used for multiple invocations of to_string could take the buffer and "consume" portion of it by taking it by reference. Something like this:

char buffer[100];
auto buf = create_consumable( buffer );
pprint("Multiple Foos: {} / {}", to_string( buf, foo1 ), to_string( buf, foo2 ) );

Which of cause won't work as both calls to to_string() must have a side effect on buf, but the order of evaluating would be undefined.

Thanks for your suggestion.

from pprintpp.

TorstenRobitzki avatar TorstenRobitzki commented on June 11, 2024

and of cause, it requires some kind of support for std::string in pprint.

from pprintpp.

DBJDBJ avatar DBJDBJ commented on June 11, 2024

Encapsulation and decoupling. That is a fundamental postulate. Not a "suggestion".

There is a rumor some of them ancients have developed ancient parts of std:: twilight zone.
Your line of thinking is not that uncommon. Whan I aksed that question, in particular std::exception has been brought to my meek persona attention, so I can learn by example:

// two instances of some offsprings of std::exception
// x1 and x2, came in
pprintp("Look Ma, no integration and no std::strings ! {s} {s} ",  x1.what(), x2.what() ) ;

They actully use const char * ... Silly people ...

from pprintpp.

tfc avatar tfc commented on June 11, 2024

@TorstenRobitzki i am glad that the language turns out to be useful in your project! I keep seeing new issue items very late because for some reason i don't get emails about it.

I think the cleanest way to extend this is this:

  • for your type MyType provide some nonstandard %FOO format implementation in your printf implementation that handles the formatting of the variable's content in the output. This part would happen without any change to pprintpp yet.
  • then add something like
    namespace pprintpp {
    template <> struct type2fmt<MyType> { using type = char_tl_t<'F', 'O', 'O'>; };
    }
    as seen between the other types here.

Is this something that might work for you?

pprintpp is simply a format string preprocessor that creates no runtime code. Thinking about different models might be possible, but i guess we would need kind of rethink the whole thing from the beginning (which would be fun of course). This is why i suggest this approach with separated concerns.

from pprintpp.

TorstenRobitzki avatar TorstenRobitzki commented on June 11, 2024

Yes, we are fully aware, that pprintpp "just" turns a typelist and a format string in a new format, but we though, that we are probably not the only and first one, that have the requirements to use user defined types. As we are basically using snprintf() and not printf(), we wrapped snprintf() already to have some formatting like this:

char buffer[ 100 ];
const std::size_t buffer_used  = format( buffer, "{s} = {}\r\n", "Elf", 11 );

I though about your approach already, but rejected the idea, because it inverses the usual library dependencies (in addition, we have printf() in conan package that would then be under constant change).

I'm currently thinking of wrapping buffer in some kind of type to select a different overload of snprintf() and to change pprintf() to check if unsupported types (aka user defined) type support a specific overloaded function, that could be used to pass the buffer and the object to, to fill the buffer.

I also try to understand, if pprintpp would still be the right place to start with or if it might be easier to start from scratch.

from pprintpp.

DBJDBJ avatar DBJDBJ commented on June 11, 2024

@TorstenRobitzki first I hope you do not mind my approach before. :)

Your project has requirements which we do not know but, I really do not see what might be wrong with:

// just a sketch
struct Foo {
    whatever data_ ;
    const char * to_string () const {
        // 1. somehow put data_ string presentation to this->buffy_
        // 2. return the native pointer to it
        return this->buffy_ ;
    };
    private: 
      char buffy_[BUFSIZ]{char(0)};
} ;

 // ... somewhere else
void test ( Foo const & foo_ )  {
    pprintf(" Foo instance: { s } \n\n",  foo_.to_string() ) ;
} 

pprintf is simple, effective and feasible as it is ... Perhaps we should think of it as we think of stdio.h printf() : it is there it is useful and it is unchangeable :)

from pprintpp.

TorstenRobitzki avatar TorstenRobitzki commented on June 11, 2024

Your project has requirements which we do not know but, I really do not see what might be wrong with:

Well, having a buffer inside every data type that has to have a string representation is simply overkill and it won't work for enumerations and it requires support by the user defined type, which might be unsuitable for types from existing libraries.

from pprintpp.

DBJDBJ avatar DBJDBJ commented on June 11, 2024

@TorstenRobitzki , The point is in the last sentence :

pprintf is simple, effective and feasible as it is ... Perhaps we should think of it, as we think of stdio.h printf() : it is there it is useful and it is unchangeable :)

Yes ... "callable arguments" is one OK way of doing it. It does not change pprintf ... There are many C++ variadic arguments based designs, working that way, for example...

from pprintpp.

TorstenRobitzki avatar TorstenRobitzki commented on June 11, 2024

Thanks for the open discussion. I will think about this a little bit longer, but I think the solution to our requirements are somewhere outside of pprintfpp.

from pprintpp.

DBJDBJ avatar DBJDBJ commented on June 11, 2024

@TorstenRobitzki You might consider this schema

#include "../pprintpp.hpp"
#include <cassert>
#include <cstdio>
#include <memory>

using namespace std;
/*
somewhat inspired with
https://msdn.microsoft.com/en-us/magazine/dn913181.aspx
*/
template <typename T>
inline T frm_arg(T value) noexcept
{
	return value;
}

template<typename ... Args>
inline auto	to_buff
(char const* fmt, Args ...args)
noexcept -> unique_ptr<char[]>
{
	assert(fmt != nullptr);
	// 1: what is the size required
	size_t size = 1 + std::snprintf(nullptr, 0, fmt, frm_arg(args) ...);
	assert(size > 0);
	// 2: use it at runtime
	auto buf = std::make_unique<char[]>(size + 1);
	size = std::snprintf(buf.get(), size, fmt, frm_arg(args) ...);
	assert(size > 0);
	return buf;
}
///////////////////////////////////////////////////////////////////////
struct Foo {
	const char* name = "Foo";
};

inline constexpr char const * frm_arg(Foo const & foo_ ) noexcept
{
	return foo_.name;
}
///////////////////////////////////////////////////////////////////////
extern "C" int test_4(int, wchar_t* [])
{
	auto rez{ to_buff(
		"\n\nFoo: %s, Foo: %s, %s %d\n\n", Foo{"A"}, Foo{"B"}, "The answer is:", 42
	  )};
	pprintf("{s}", rez.get() );
	return EXIT_SUCCESS;
}

from pprintpp.

Related Issues (15)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.