using custom deleter with unique_ptr - c++

With shared_ptr you can use a custom deleter, like:
auto fp = shared_ptr<FILE>( fopen("file.txt", "rt"), &fclose );
fprintf( fp.get(), "hello\n" );
and this will remember to fclose the file regardless of how the function exits.
However, it seems a bit overkill to refcount a local variable, so I want to use unique_ptr:
auto fp = unique_ptr<FILE>( fopen("file.txt", "rt"), &fclose );
however, that does not compile.
Is this a defect? Is there a simple workaround? Im I missing something trivial?

Should be
unique_ptr<FILE, int(*)(FILE*)>(fopen("file.txt", "rt"), &fclose);
since http://en.cppreference.com/w/cpp/memory/unique_ptr
or, since you use C++11, you can use decltype
std::unique_ptr<FILE, decltype(&fclose)>

The above answer while its intent is OK and in practice compiles and works is wrong, because it is not specified that you are allowed to take the address of a standard library function. A C++ library implementation is allowed to provide different overloads or more parameters (with default arguments). Only calling the library function is sanctioned by the standard. Therefore, you need to wrap the call to fclose in your own function implementation or lambda, such as
unique_ptr<FILE, int(*)(FILE*)>(fopen("file.txt", "rt"),
[](FILE *fp)->int{ if(fp) return ::fclose(fp); return EOF;});
or wait for unique_resourceof https://wg21.link/p0052 to become standardized, but even there you need to use the lambda or a deleter function (object), see the more recent versions of p0052.

Note that in a real program you may want to check and act upon the return value of fclose, which could be awkward from within a destructor: you don't get to return a value and throwing exceptions from destructors is a bad idea. Similar considerations may or may not apply for other types of pointer.
With that caveat out of the way, an alternative approach would be to specify the deleter as a functor:
struct file_deleter {
void operator()(std::FILE* fp) { std::fclose(fp); }
};
using unique_file = std::unique_ptr<std::FILE, file_deleter>;
The type alias allows you to simply write:
unique_file f{ std::fopen("file.txt", "rt") };
This is more ergonomic than having to pass an additional pointer or a lambda every time you create a pointer. The use of a functor type also means that the unique_ptr does not have to carry around a separate pointer for the deleter, which allows for space savings relative to the other approaches. To see this, I use the following code:
int main()
{
std::unique_ptr<FILE, decltype(&fclose)> f1{ nullptr, &fclose };
std::unique_ptr<std::FILE, void(*)(std::FILE*)> f2{
nullptr, [](std::FILE* p) { std::fclose(p); } };
unique_file f3{ nullptr };
std::FILE* f4{ nullptr };
std::cout << "sizeof(f1) = " << sizeof(f1) << '\n';
std::cout << "sizeof(f2) = " << sizeof(f2) << '\n';
std::cout << "sizeof(f3) = " << sizeof(f3) << '\n';
std::cout << "sizeof(f4) = " << sizeof(f4) << '\n';
}
Using MSVC building for an x64 target, I get the following output:
sizeof(f1) = 16
sizeof(f2) = 16
sizeof(f3) = 8
sizeof(f4) = 8
In this specific implementation, for the case using the functor the unique_ptr is the same size as a raw pointer, which is not possible for the other approaches.

Related

Using a variable that was defined in an if statement before

int main() {
if(i = 0) {
myclass1 a = "Example1";
}
else {
myclass2 a = "Example2";
}
cout << a << endl;
}
I know a way to do this is by defining it outside the block but what if I have not decided what type a is before checking the condition of i?
If you are able to use c++17 you can use the std::variant or std::any in case your types haven't common base class. These classes are type-safe containers for any or specified types. An example with std::variant can be the following:
#include <iostream>
#include <string>
#include <variant>
int main() {
bool input = false;
std::cin >> input;
std::variant<int, long, double, std::string> myVariant;
if(input)
myVariant = "Example1";
else
myVariant = 3.14;
std::visit([](auto&& arg) { std::cout << arg << std::endl; }, myVariant);
}
Instead of c++17 you also can use the boost::variant or the boost::any.
C++ is a statically typed language, and requires the type of variables being used in the code to be known at compile time.
There's no way to write a C++ program where a statement like std::cout << a; is compiled and the type of a is not known until run-time.
For that you need a dynamically typed language, like for example Python or JavaScript.
int main() {
auto call = [](auto a) {
std::cout << a << std::endl;
};
if(i = 0)
call(myclass1 { "Example1" });
else
call(myclass2 { "Example2" });
}
You could try polymorphism.
Assuming myclass1 and myclass2 "implement" a class called myclass, you can do something like this:
int main() {
myclass*a;
if (i=0) {
a = new myclass1("Example1");
} else {
a = new myclass2("Example2");
}
cout<<*a<<endl;
}
If you want to actively use the type myclass1 or myclass2 later on, you can use dynamic_cast, but depending on your needs and what behaviour you implement in your inherited classes and your base class, thay may not be necessary.
Note I use a raw pointer here, since it's a short-lived object and it's clear the program has ended. I encourage you to read about smart pointers and use them appropriately to avoid memory leaks. Beware memory leaks in some platforms persist until after a reboot, it may be needed to manually free (delete) allocated memory. More about all that here.
This definitively calls for polymorphism, and optionally, if you want to have it a bit more elegant, the factory pattern. The factory pattern is no magic, it just hides the if within a nice wrapper.
Why not another approach, such as e.g. std::variant which is basically a union in disguise? Well, it's nice if you are able to store different kinds of things, or even any kind (std::any) under the same name, but it is not very useful since you also want to do something meaningful with the object. If you want to do completely different, unrelated things, then you can as well have different objects scoped by the if blocks (and with completely different code). If, however, you want to do the same or similar things on different objects, then they (usually) need to be the same or a related type.
Different types typically do not have the same data members or the same publicly accessible member functions. So, doing the same thing on a source code level with different types typically doesn't work (except by coincidence).
But if two classes do have identical subsets on their interfaces, and you want to be able to do it in one or the other way interchangeably, then inheriting from a base class is the most natural and idiomatic thing to do. That's what polymorphism was invented for. Use the idiomatic thing.
(You can get the same net effect of calling functions with the same name on different, unrelated types via a template helper, and presumed that the names that you use exist, that will just work, but it's not nearly as good style, and it causes huge bloat by instanciating the function twice).
I'll try to give you a practical answer that assumes you're used to doing this sort of thing in JavaScript or something and just trying to write code in C++.
First, you should understand that in C++, cout << a. Can actually call a completely different method depending on the type of a. For that reason, it doesn't make any sense to write cout << a when you don't know anything about that type. In fact, you can't do anything at all with a unless you know enough about the type for C++ to decide which method or operator you want to invoke.
If both of your classes have an acceptable common base, then you could do something this:
int main() {
base_class *pa;
my_class1 a1;
my_class2 a2;
if(i = 0) {
a1 = "Example1";
pa = &a1;
}
else {
a2 = "Example2";
pa = &a2;
}
cout << *pa << endl;
}
Note that when you write cout << *pa, you are not necessarily calling the same method that cout << a would use. In the first case you are calling a method that knows how to output all subclasses of base_class, while in the second case you may be calling a method that was written specifically for myclass1 or myclass2.
When there is no acceptable base class, then we just don't write code like that in C++:
int main() {
if(i = 0) {
myclass1 a = "Example1";
cout << a << endl;
}
else {
myclass2 a = "Example2";
cout << a << endl;
}
}
Remember that the two methods being called in these cases can be completely different methods. It's exactly like calling cout.printClass1(a) vs. cout.printClass2(a). C++ lets you use the same name for completely different methods when it can figure out which one you want to call based on the argument types.
JavaScript doesn't have any magic that could automatically choose between printClass1 and printClass2 when you write cout.callWhatever(a), and neither does C++. In both languages, if you have to call completely different methods for myclass1 vs. myclass2, then you write different calls.
I had such code myself, when I was in fact trying different variations of the same code. Then I realized the best option would be to use a preprocessor #if and it solved my problem:
#define VARIATION 2
...
#if VARIATION == 1
myclass1 a = "Example1";
#else
myclass2 a = "Example2";
#endif
I know it probably doesn't solve yours, but at least it is a workaround.
If it is this specific problem I would think that this would be much more easier
int main(){
if(i == 0) //You wrote i=0 !! silly mistake
std::cout << myclass1("Example1");
else
std::cout << myclass2("Example2");
}
or you can choose
template<class T>
void foo(T out)
{
std::cout << out;
}
int main()
{
if( i==0 )
foo(myclass1("ex1"));
else
foo(myclass2("ex2"));
}
else
this is the way to go
And I would advise against using cout here as it may not have overloads to accept your user defined class.

Is it possible to avoid copying arguments to a lambda function?

I'd like to manage file descriptors using a Handle, and I want to use lambda expressions to process them. I'd like to use RAII to manage the underlying file descriptors. One option is to handle invalid values for descriptors (e.g. -1). However, I'd prefer for a handle to always be valid.
I've found that I can't seem to avoid invoking the copy constructor at least once. Here is a working example:
#include <fcntl.h>
#include <unistd.h>
#include <functional>
#include <system_error>
#include <iostream>
class Handle
{
public:
Handle(int descriptor) : _descriptor(descriptor) {}
~Handle()
{
std::cerr << "close(" << _descriptor << ")" << std::endl;
::close(_descriptor);
}
Handle(const Handle & other) : _descriptor(::dup(other._descriptor))
{
std::cerr << "dup(" << other._descriptor << ") = " << _descriptor << std::endl;
if (_descriptor == -1) throw std::system_error(errno, std::generic_category(), "dup");
}
int descriptor() const { return _descriptor; }
private:
int _descriptor;
};
Handle open_path(const char * path)
{
return ::open("/dev/random", O_RDONLY);
}
void invoke(std::function<void()> & function)
{
function();
}
int main(int argc, const char * argv[]) {
// Using auto f = here avoids the copy, but that's not helpful when you need a function to pass to another function.
std::function<void()> function = [handle = open_path("/dev/random")]{
std::cerr << "Opened path with descriptor: " << handle.descriptor() << std::endl;
};
invoke(function);
}
The output of this program is:
dup(3) = 4
close(3)
Opened path with descriptor: 4
close(4)
I know that the handle is being copied because it's being allocated by value within the std::function, but I was under the impression std::function could be heap allocated in some cases, which would perhaps avoid the copy (I guess this is not happening though).
There are a number of options, e.g. heap allocation, orusing a sentinel value (e.g. -1) which is checked. However, I'd like to have an invariant that a handle is always valid. It's sort of a matter of style and invariants.
Is there any way to construct the handle within the stack frame of the std::function to avoid copying, or do I need to take a different approach?
Perhaps as an additional point: to what extent can we rely on std::function to avoid copying it's arguments when it's created?
First, let's get this out of the way: std::function is completely orthogonal to lambdas. I wrote an article, "passing functions to functions" that should clarify their relationship and illustrate various techniques that can be used to implement higher-order functions in modern C++.
Using auto f = here avoids the copy, but that's not helpful when you need a function to pass to another function.
I disagree. You can use a template in invoke or something like function_view (see LLVM's FunctionRef for a production-ready implementation, or my article for another simple implementation):
template <typename F>
void invoke(F&& function)
{
std::forward<F>(function)();
}
void invoke(function_view<void()> function)
{
function();
}
Relying on elision or moving with std::function is not enough. Since std::function is required to be copyable, there's always a chance you might copy your Handle by accident elsewhere.
What you need to do instead is to wrap your Handle in something that will not invoke the copy constructor on copy. An obvious choice is a pointer. And an obvious choice of pointer would be a manged one like std::shared_ptr.
I made a few changes to your Handle class for testing (print statements for dtor, ctor, copy ctor), so I'll show those first:
class Handle
{
public:
Handle(int descriptor) : _descriptor(descriptor) {std::cerr<<"Default ctor, descriptor: " << _descriptor << std::endl;}
~Handle()
{
std::cerr << "Dtor. close(" << _descriptor << ")" << std::endl;
}
Handle(const Handle & other) : _descriptor(other._descriptor+1)
{
std::cerr << "Copy ctor. dup(" << other._descriptor << ") = " << _descriptor << std::endl;
}
int descriptor() const { return _descriptor; }
private:
int _descriptor;
};
Next let's modify open_path to return a shared_ptr:
std::shared_ptr<Handle> open_path(const char * path)
{
return std::make_shared<Handle>(0);
}
And then we'll make a slight modification to our lambda in main:
std::function<void()> function = [handle = open_path("/dev/random")]{
std::cerr << "Opened path with descriptor: " << handle->descriptor() << std::endl;
};
Our output now becomes:
Default ctor, descriptor: 0
Opened path with descriptor: 0
Dtor. close(0)
Live Demo

C++ distinguish Lambdas from Function pointers inside a vector

I'm writing a little event manager class where I store some function pointers inside a vector. I use std::function<void(int)> as vector type, I tested inserting inside it lambdas and normal functions and it works:
void t(int p){
/*things*/
}
[...]
event.bind([](int p){/*things*/});
event.bind(t);
Now, (at a certain point I need to delete lambdas but not functions,) my question is:
Is it possible to distinguish lambdas from functions? If yes, how?
EDIT:
Since I clarified my doubts, this question becomes just what the title says
The real answer is: you don't want to do this. It defeats the point of type-erasing functors if you actually want to know the original type also in case of whatever. This just smells like bad design.
What you are potentially looking for is std::function::target_type. This is a way to pull out the underlying type_info of the target function that the function object is storing. Each type_info has a name(), which can be demangled. Note that this is a very deep rabbit hole and you're basically going to have to hard-code all sorts of weird edge-cases. As I've been doing thanks to Yakk's very loving help.
Different compilers mangle their lambda names differently, so this approach doesn't even resemble portability. Quick checking shows that clang throws in a $ while gcc throws {lambda...#d}, So we can attempt to take advantage of that by writing something like:
bool is_identifier(std::string const& id) {
return id == "(anonymous namespace)" ||
(std::all_of(id.begin(), id.end(),
[](char c){
return isdigit(c) || isalpha(c) || c == '_';
}) && !isdigit(id[0]));
}
bool is_lambda(const std::type_info& info)
{
std::unique_ptr<char, decltype(&std::free)> own {
abi::__cxa_demangle(info.name(), nullptr, nullptr, nullptr),
std::free
};
std::string name = own ? own.get() : info.name();
// drop leading namespaces... if they are valid namespace names
std::size_t idx;
while ((idx = name.find("::")) != std::string::npos) {
if (!is_identifier(name.substr(0, idx))) {
return false;
}
else {
name = name.substr(idx+2);
}
}
#if defined(__clang__)
return name[0] == '$';
#elif defined(__GNUC__)
return name.find("{lambda") == 0;
#else
// I dunno?
return false;
#endif
}
And then throw that in your standard erase-remove idiom:
void foo(int ) { }
void bar(int ) { }
long quux(long x) { return x; }
int main()
{
std::vector<std::function<void(int)>> v;
v.push_back(foo);
v.push_back(bar);
v.push_back(quux);
v.push_back([](int i) { std::cout << i << '\n';});
std::cout << v.size() << std::endl; // prints 4
v.erase(
std::remove_if(
v.begin(),
v.end(),
[](std::function<void(int)> const& f){
return is_lambda(f.target_type());
}),
v.end()
);
std::cout << v.size() << std::endl; // prints 3
}
No, not in general.
A std::function<void(int)> can store a function pointer to any function that can be called by passing a single rvalue int. There are an infinite number of such signatures.
The type of a lambda is an unique anonymous class for each declaration. Two distinct lambdas do not share any type relationship.
You can determine of a std::function<void(int)> stores a variable of a specific type, but in both the function pointer and lambda case there is an unbounded number of different types that can be stored in the std::function to consider. And you can only test for "exactly equal to a type".
You can access the type id information, but there is no portable representation there, and generally using that information for anything other than identity matching (and related) or debugging is a bad idea.
Now, a restricted version of the question (can you tell if a std::function<void(int)> contains a function pointer of type void(*)(int)) is easy to solve. But in general, doing so remains a bad idea: first, because it is delicate (code far away from the point you use it, like a subtle change to the function signature, can break things), and second, inspecting and changing your behavior based on the type stored in a std::function should only be done in extreme corner cases (usually involving updating your code from using void* style callbacks to std::function style callbacks).
Be it a function pointer or lambda, it ends up as a std::function<void(int)> in the vector. It is then std::function<void(int)>'s responsibility to manage the function pointer or lambda, not yours. That means, you just remove the std::function<void(int)>s you want from the vector. The destructor of std::function<void(int)> knows how to do things right. In your case, that would be doing nothing with function pointers and invoking the destructor of lambdas. std::function<void(int)> enables you to treat different things in a nice and uniform way. Don't misuse it.
NOTE: This answer presupposes that there is a finite, distinct number of function signatures that may be assigned as event handlers. It assumes that assigning any-old function with the wrong signature is a mistake.
You can use std::function::target to determine which ones are the function pointers and by process of elimination figure out which ones must be the lambdas:
void func1(int) {}
void func2(double) {}
int main()
{
std::vector<std::function<void(int)>> events;
events.push_back(func1);
events.push_back([](int){});
events.push_back(func2);
for(auto& e: events)
{
if(e.target<void(*)(int)>())
std::cout << "funcion int" << '\n';
else if(e.target<void(*)(double)>())
std::cout << "funcion double" << '\n';
else
std::cout << "must be lambda" << '\n';
}
}
This works because std::function::target returns a null pointer if the parameter type doesn't match.
Single variable example:
void func(int) {}
int main()
{
std::function<void(int)> f = func;
if(f.target<void(*)(int)>())
std::cout << "not a lambda" << '\n';
}

Storing and calling functions of different arguments in one function container

Here is a sample design code of what I want to achieve. Basically I wanna store handler functions for different handlerNames and these handler functions can be of variable arguments.
The handler functions should be called on events with the required arguments are passed with Script::Handle(...)
How can I achieve this? Maybe its possible with Variadic Templates?
class Script
{
public:
Script() { /* ... */ }
template<typename TFunction>
void AddHandler(const char *handlerName, TFunction &&function)
{
_handlerMap[handlerName] = std::move(function);
}
void Handle(const char *handlerName, ...)
{
_handlerMap[handlerName](...);
}
private:
typedef std::map<std::string, std::function<void()>> HandlerMapType;
HandlerMapType _handlerMap;
};
//Handler functions
handlerOne() { std::cerr << "One"; }
handlerTwo(std::string a1, int a2) { std::cerr << "Two"; }
handlerThree(bool a1) { std::cerr << "Three"; }
int main(int argc, char **argv)
{
Script script;
script.AddHandler("One", std::bind(&handlerOne));
script.AddHandler("Two", std::bind(&handlerTwo));
script.AddHandler("Three", std::bind(&handlerThree));
script.Handle("One");
script.Handle("Two, "string", 96);
script.Handle("Three", true);
script.Handle("Three", "what should happen here?"); //String passed instead of bool
}
Let me prefix by saying that this is not a trivial thing to do in C++. And I will go as far to say that you should consider whether this is really something you need in your use case. In your example, you are asking for genericism that you can't really use. You will in any case need to know the signature of the function you are calling to call it properly; in that case what purpose is served by putting them in a container?
Generally, you'd do something like this if you are writing a middle layer of code. In your example, this would be equivalent to writing code that enables another user to call Handle. A common concrete example of this is to write a factory where objects in the factory may be instantiated using different arguments. However, it can't really be "different" arguments, at least not without some crazy casting. The solution is to make all the functions take the same argument, but make the argument a dynamic type that can store whatever arguments you want:
using argument_type = std::unordered_map<std::string, boost::any>;
void print(const argument_type & arg) {
auto to_print = boost::any_cast<std::string>(arg["to_print"]);
std::cerr << to_print << std::endl;
}
void print_none(const argument_type & arg) {
std::cerr << "none" << std::endl;
}
using my_func_t = std::function<void(const argument_type &)>;
std::vector<my_func_t> v;
v.emplace_back(print);
v.emplace_back(print_none);
// create some argument_types, feed them to f.
The above is not code that has been tested, nor with a working main, but I think this should give you a sense of how you could accomplish what you want.
edit: I thought about it a bit more, and I decided to elaborate a bit more on the "crazy casting" way. I suppose it's not really more crazy, but I strongly prefer what I showed above. The alternative is to completely type erase the functions themselves, and pass the arguments using a variadic template.
void print(std::string to_print) {
std::cerr << to_print << std::endl;
}
void print_none() {
std::cerr << "none" << std::endl;
}
std::vector<boost::any> v;
v.emplace_back(std::function<void(std::string)>(print));
v.emplace_back(std::function<void(void)>(print_none));
template <typename ... Args>
void call(const std::vector & funcs, int index, Args... args) {
auto f = boost::any_cast<std::function<void(Args...)>>(funcs[index]);
f(std::forward<Args>(args)...);
}
// unsure if this will actually work
call(f, 0, std::string("hello"));
The code above is very fragile though, because the types you pass to call will be deduced against, and then the cast will try to cast to a std::function that matches that signature. That exact signature. I don't have a lot of confidence that this will work out; if it's a reference, vs value, vs rvalue, etc. Casting back to a different std::function than what you put in is undefined behavior.
In summary, I'd either try to avoid needing to do this entirely, or go with the first solution. It's much less fragile, and it's better to be upfront about the fact that you are erasing the signatures of these functions.

c++ stringstream to ostream to string

I would like to be able to do:
foo(stringstream()<<"number = " << 500);
EDIT: single line solution is crucial since this is for logging purposes. These will be all around the code.
inside foo will print the string to screen or something of the sort.
now since stringstream's operator<< returns ostream&, foo's signature must be:
foo(ostream& o);
but how can I convert ostream& to string? (or char*).
Different approaches to achieving this use case are welcome as well.
The obvious solution is to use dynamic_cast in foo. But the given
code still won't work. (Your example will compile, but it won't do what
you think it should.) The expression std::ostringstream() is a
temporary, you can't initialize a non-const reference with a temporary,
and the first argument of std::operator<<( std::ostream&, char const*)
is a non-const reference. (You can call a member function on a
temporary. Like std::ostream::operator<<( void const* ). So the code
will compile, but it won't do what you expect.
You can work around this problem, using something like:
foo( std::ostringstream().flush() << "number = " << 500 );
std::ostream::flush() returns a non-const reference, so there are no
further problems. And on a freshly created stream, it is a no-op.
Still, I think you'll agree that it isn't the most elegant or intuitive
solution.
What I usually do in such cases is create a wrapper class, which
contains it's own std::ostringstream, and provides a templated
member operator<< which forwards to the contained
std::ostringstream. Your function foo would take a const
reference to this—or what I offen do is have the destructor call
foo directly, so that the client code doesn't even have to worry about
it; it does something like:
log() << "number = " << 500;
The function log() returns an instance of the wrapper class (but see
below), and the (final) destructor of this class calls your function
foo.
There is one slight problem with this. The return value may be copied,
and destructed immediately after the copy. Which will wreck havoc with
what I just explained; in fact, since std::ostringstream isn't
copyable, it won't even compile. The solution here is to put all of the
actual logic, including the instance of std::ostringstream and the
destructor logic calling foo in a separate implementation class, have
the public wrapper have a boost::shared_ptr to it, and forward. Or
just reimplement a bit of the shared pointer logic in your class:
class LogWrapper
{
std::ostringstream* collector;
int* useCount;
public:
LogWrapper()
: collector(new std::ostringstream)
, useCount(new int(1))
{
}
~LogWrapper()
{
-- *useCount;
if ( *useCount == 0 ) {
foo( collector->str() );
delete collector;
delete useCount;
}
}
template<typename T>
LogWrapper& operator<<( T const& value )
{
(*collector) << value;
return *this;
}
};
Note that it's easy to extend this to support optional logging; just
provide a constructor for the LogWrapper which sets collector to
NULL, and test for this in the operator<<.
EDITED:
One other thing occurs to me: you'll probably want to check whether the
destructor is being called as a result of an exception, and not call
foo in that case. Logically, I'd hope that the only exception you
might get is std::bad_alloc, but there will always be a user who
writes something like:
log() << a + b;
where the + is a user defined overload which throws.
I would suggest you to use this utility struct:
struct stringbuilder
{
std::stringstream ss;
template<typename T>
stringbuilder & operator << (const T &data)
{
ss << data;
return *this;
}
operator std::string() { return ss.str(); }
};
And use it as:
void f(const std::string & s );
int main()
{
char const *const pc = "hello";
f(stringbuilder() << '{' << pc << '}' );
//this is my most favorite line
std::string s = stringbuilder() << 25 << " is greater than " << 5 ;
}
Demo (with few more example) : http://ideone.com/J995r
More on my blog : Create string on the fly just in one line
You could use a proxy object for this; this is a bit of framework, but if you want to use this notation in a lot of places then it may be worth it:
#include <iostream>
#include <sstream>
static void foo( std::string const &s )
{
std::cout << s << std::endl;
}
struct StreamProxy
{
std::stringstream stream;
operator std::string() { return stream.str(); }
};
template <typename T>
StreamProxy &operator<<( StreamProxy &s, T v )
{
s.stream << v;
return s;
}
static StreamProxy make_stream()
{
return StreamProxy();
}
int main()
{
foo( make_stream() << "number = " << 500 );
}
This program prints
number = 500
The idea is to have a little wrapper class which can be implicitely converted into a std::string. The << operator is simply forwarded to the contained std::stringstream. The make_stream() function is strictly speaking not necessary (you could also say StreamProxy(), but I thought it looks a bit nicer.
A couple of options other than the nice proxy solution just presented by Frerich Raabe:
Define a static string stream variable in the header that defines the logging function and use the comma operator in your invocation of the logging function so that this variable is passed rather than the ostream& returned by the stream insertion operator. You can use a logging macro to hide this ugliness. The problem with this solution is that it is a bit on the ugly side, but this is a commonly used approach to logging.
Don't use C++ I/O. Use a varargs C-style solution instead. Pass a format string as the first argument, with the remaining arguments being targets for that format string. A problem with this solution is that even if your compiler is smart enough to ensure that printf and its cousins are safe, the compiler probably won't know that this new function is a part of the printf family. Nonetheless, this is also a commonly used approach.
If you don't mind using macros functions, you can make the logging function accept const string&, and use the following macro
#define build_string(expr) \
(static_cast<ostringstream*>(&(ostringstream().flush() << expr))->str())
And suppose you foo has signature void foo(const string&), you only need the one-liner
foo(build_string("number = " << 500))
This was inspired by James Kanze's answer about static_cast and stringstream.flush. Without the .flush() the above method fails with unexpected output.
Please note that this method should not leak memory, as temporary values, whether in the pointer form or not, are still allocated on the stack and hence destroyed upon return.
Since you're converting to string anyways, why not
void foo(const std::string& s)
{
std::cout << "foo: " << s << std::endl;
}
...
std::stringstream ss;
ss << "number = " << 500;
foo(ss.str());
This is not possible. As the name ostream implies, it is used for output, for writing to it. You could change the parameter to stringstream&. This class has the method str() which returns a std::string for your use.
EDIT I did not read the issue with operator << returning ostream&. So I guess you cannot simply write your statements within the functions argument list but have to write it before.
You can create a small wrapper around std::ostringstream that will convert back to std::string on use, and have the function take a std::string const &. The first approach to this solution can be found in this answer to a different question.
On top of that, you can add support for manipulators (std::hex) if needed.