Using tuple as a parameter of a function - c++11

Hi I'm trying to pass a tuple as a parameter to a function.
I would like to not to specify the amount of elements in the tuple (I followed this example: tuple as function argument)
What is missing now is how I can count the number of element into the tuple in order to access it with std::get
#include<tuple>
#include<iostream>
template <typename... T> void fill(std::tuple<T...> values) {
std::cout << std::tuple_size<T...>::value << '\n';
//std::cout << std::get<0>(values) << '\n';
//std::cout << std::get<1>(values) << '\n';
}
int main() {
fill(std::make_tuple(2.));
fill(std::make_tuple(2., 5));
}
tuple_size seems not suitable to be used (https://en.cppreference.com/w/cpp/utility/tuple/tuple_size)

Lets look at the example in the provided reference:
template <class T>
void test(T t)
{
int a[std::tuple_size<T>::value]; // can be used at compile time
std::cout << std::tuple_size<T>::value << '\n'; // or at run time
}
int main()
{
test(std::make_tuple(1, 2, 3.14));
}
From this example (as well as from the reference itself, see e.g. the second declaration), it could be deduced that the template argument to std::tuple_size is the tuple type.
As in (in your case)
std::cout << std::tuple_size<std::tuple<T...>>::value << '\n';
// ^^^^^^^^^^^^^^^^
// Note: The tuple type is used here

Related

Why does the index of a `char **` type give the whole string?

Consider this snippet:
#include <iostream>
using std::cout;
using std::endl;
int main()
{
char c[] = {'a','b','c','\0'};
char *pc = c;
char **ppc = &pc;
cout << ppc[0] << endl;
}
This prints abc as output. Why does the index of a pointer to pointer to char return the whole string? Here, ppc only points to another pointer that points to a single char. How does it know about the whole string and why would it return it?
You have to understand what std::cout is and why it treats a char* as a "string".
Lets start:
std::cout is an instance of an std::ostream and std::ostream has a lot of operators. What does it mean?
The implementation of std::ostream can, but only as an example here, written like:
class ostream
{
// ... a lot more code for constructors and others
ostream& operator <<( const int );
ostream& operator <<( const double );
ostream& operator <<( char* ); <<< this is the implementation you search for!
// a long list of more special overloads follow
};
And the implementation simply puts out the "string" which the char* points to.
What you see is simply a special overload of the operator<< for the std::ostream class.
OK, the real implementation uses a non-member overload, but that is not important for understanding how std::ostream works in principal.
For more details see: std::ostream::operator<<()
Character and character string arguments (e.g., of type char or const char*) are handled by the non-member overloads of operator<<. Attempting to output a character using the member function call syntax (e.g., std::cout.operator<<('c');) will call one of overloads (2-4) and output the numerical value. Attempting to output a character string using the member function call syntax will call overload (7) and print the pointer value instead.
These are equivalent:
cout << ppc[0] << endl;
cout << *( ppc + 0 ) << endl;
cout << *ppc << endl;
cout << *(&pc) << endl;
cout << pc << endl;

Selecting which overload is used in c++11

In the following code, as none of the arguments is const, i can't understand why the second overload is called in the 3 following cases.
#include <iostream>
#include <algorithm>
using namespace std;
void ToLower( std::string& ioValue )
{
std::transform( ioValue.begin(), ioValue.end(), ioValue.begin(), ::tolower );
}
std::string ToLower( const std::string& ioValue )
{
std::string aValue = ioValue;
ToLower(aValue);
return aValue;
}
int main()
{
string test = "test";
cout<<"Hello World" << endl;
// case 1
cout << ToLower("test") << endl;
// case 2
cout << ToLower(static_cast<string>(test)) << endl;
// case 3
cout << ToLower(string(test)) << endl;
}
In all 3 cases you are creating a temporary std::string, this is an unnamed object, an R-value. R-values aren't allowed to bind to non-const l-value references (T&) and so only the overload taking const std::string& ioValue is valid.
The reasoning is the return type is std::string for the second function but void for the first. std::cout << (void) << std::endl is not a valid set of operations. std::cout << (std::string) << std::endl is. If you return a std::string& from the first function you'd probably see #2 & #3 probably use your first function call.

Why reference_wrapper behaves differently for built-in types?

I have the following use of std::reference_wrapper for a build in type (double) and for a user defined type (std::string).
Why do they behave differently in the case of the stream operator?
#include<functional> //reference wrapper
#include<iostream>
void fd(double& d){}
void fs(std::string& s){}
int main(){
double D = 5.;
std::reference_wrapper<double> DR(D);
std::cout << "DR = " << DR << std::endl; //ok
fd(DR); // ok
std::string S = "hello";
std::reference_wrapper<std::string> SR(S);
std::cout << "SR = " << static_cast<std::string&>(SR) << std::endl; // ok
std::cout << "SR = " << SR << std::endl; // error: invalid operands to binary expression ('basic_ostream<char, std::char_traits<char> >' and 'std::reference_wrapper<std::string>')
fs(SR); // ok
}
http://coliru.stacked-crooked.com/a/fc4c614d6b7da690
Why in the first case DR is converted to double and printed and in the second it is not? Is there a work around?
Ok, I see now, in the ostream case I was trying to called a templated function that is not resolved:
#include<functional> //reference wrapper
void double_fun(double const& t){};
template<class C>
void string_fun(std::basic_string<C> const& t){};
int main(){
double D = 5.;
std::reference_wrapper<double> DR(D);
double_fun(DR); //ok
std::string S = "hello";
std::reference_wrapper<std::string> SR(S);
string_fun(SR); // error: no matching function for call to 'string_fun'
string_fun(SR.get()); // ok
string_fun(static_cast<std::string&>(SR)); // ok
string_fun(*&SR); // would be ok if `std::reference_wrapper` was designed/coded differently, see http://stackoverflow.com/a/34144470/225186
}
For the first part TC gave you the answer. That is, operator<< for basic_string is templated, and template argument deduction doesn't look through implicit conversions.
You could alternatively call SR.get() if you don't want to explicitly to static_cast your reference wrapper.
Now for the second part, string_fun takes as input arguments std::basic_string<C> objects. When you call:
string_fun(SR);
with SR as input parameter which is of type std::reference_wrapper<std::string>, naturally you get a type mismatch.
What you can do is provide an additional overload:
template<class C>
void string_fun(std::reference_wrapper<std::basic_string<C>> const& t) {
};
Live Demo
Or if you want a more unified treatment you could define your string_fun to take template template arguments, and resolve the type with some kind of type trait magic like bellow:
template<template<typename...> class C, typename T>
void
string_fun(C<T> const &t) {
std::cout <<
static_cast<std::conditional_t<
std::is_same<
std::reference_wrapper<T>, C<T>>::value, T, std::basic_string<T>>>(t) << std::endl;
}
Live Demo

Can I use an alias for static member function templates?

Using C++11, I'd like to call a static member function template without qualifying it with the scope of its enclosing class:
struct Test {
template<typename T>
static bool Function(T x)
{ /* ... */ }
};
int x;
Test::Function(x); // I don't want to write this
Function(x); // I want to be able to write this instead
I can define another function with the same signature at global scope and forward the arguments, but I'd prefer a solution that doesn't force me to write another function. I'd also like to avoid using a macro.
This question is related:
(using alias for static member functions?)
but doesn't seem to cover the case of function templates.
Sure, you can alias the templated function if you want to do a little work with the using keyword first:
template<typename T>
using testfn = bool (*)(T);
and then create a pointer to the function with:
testfn<int> fnPointer = Test::Function;
and finally call it:
std::cout << boolalpha << fnPointer(x) << std::endl;
Live Demo
If you only ever want to bind to the case where T is int, you can do this:
using testfn = bool (*)(int);
//...
testfn fnPointer = Test::Function;
std::cout << boolalpha << fnPointer(x) << std::endl;
Live Demo 2
Edit: If you want a constexpr function pointer like in the accepted answer of the question you linked, that's a pretty simple extension:
constexpr auto yourFunction = &Test::Function<int>;
//...
std::cout << boolalpha << yourFunction(x) << std::endl;
Live Demo 3
I learned this playing with the #andyg answer (probably above mine), but it worked for me and it doesn't require putting a different alias for every template.
It requires c++14 or later though.
Step 1 - magical template alias:
template <typename T> constexpr auto funky1 = &Test::Function<T>;
Step 2 - lambda means you don't need to pass the template argument:
auto funky = [](auto in) { return funky1<decltype(in)>(in); };
full example
Also, inline full example:
#include <iostream>
struct Test {
template <typename T> static bool Function(T x) { return true; }
};
// Magical template alias
template <typename T> constexpr auto funky1 = &Test::Function<T>;
// lambda means it'll infer the template parameters when calling
auto funky = [](auto in) { return funky1<decltype(in)>(in); };
int main() {
int x = 0;
// Just use the `funky1` version, but you have to specify the template parameters
std::cout << "string: " << funky1<std::string>("I'm a string") << std::endl
<< "int: " << funky1<int>(42) << std::endl
<< "bool: " << funky1<bool>(true) << std::endl;
// Use the `funky` version, where template parameters are inferred
std::cout << "string: " << funky("I'm a string") << std::endl
<< "int: " << funky(42) << std::endl
<< "bool: " << funky(true) << std::endl;
return 0;
}

Output to logging class via operator<<

I have implemented a logging class TLogFile and now I want to overload the output operator<<.
I want to use the log like this:
TLogFile* log = new TLogFile("some arguments...");
*log << "Hello world."; // (1)
*log << "Hello world." << endl; // (2)
*log << std::hex << setw(2) << setfill('0') << someValue << endl; // (3)
I used ostream as a class member and as a friend. The class looks like this:
namespace app {
class TLogFile
{
public:
app::TLogFile& operator<< (std::string& out);
std::ostream& operator<< (std::ostream& out);
friend std::ostream& operator<< (std::ostream& out, TLogFile& o);
};
} // namespace app
Only plain text (1) is working by using the string version. A soon as I use endl (2) or iomanip (3) I get error messages:
../src/main.cpp:164:70: error: no match for 'operator<<' in 'sysdat.app::cSystemData::obj.app::cSystemObjects::applicationLog->app::TLogFile::operator<<((* & std::basic_string(((const char*)"sysdat.obj.applicationLog <<"), ((const std::allocator*)(& std::allocator()))))) << std::endl'
../src/main.cpp:164:70: note: candidates are:
../src/inc/logger.h:85:17: note: app::TLogFile& app::TLogFile::operator<<(const string&)
../src/inc/logger.h:85:17: note: no known conversion for argument 1 from '' to 'const string& {aka const std::basic_string&}'
../src/inc/logger.h:88:17: note: std::ostream& app::TLogFile::operator<<(std::ostream&)
../src/inc/logger.h:88:17: note: no known conversion for argument 1 from '' to 'std::ostream& {aka std::basic_ostream&}'
../src/inc/logger.h:93:23: note: std::ostream& app::operator<<(std::ostream&, app::TLogFile&)
../src/inc/logger.h:93:23: note: no known conversion for argument 1 from 'app::TLogFile' to 'std::ostream& {aka std::basic_ostream&}'
I believed that one of the ostream version should work.
Has anyone an idea how to overload the operator so that endl and iomanip can be used?
Your operator<< is able to take only std::ostream& and std::string&
(note: probably it should be const std::string&).
The most elegant solution I can imagine is to write a template:
class TLogFile{
protected:
std::ostream* stream;
public:
/* default ctor, copy ctor and assignment operator: */
TLogFile(std::ostream& _stream=std::clog):stream(&_stream){}
TLogFile (const TLogFile&) =default;
TLogFile& operator= (const TLogFile&) =default;
/* std::endl is overloaded,
* so I think compiler doesn't know which version to use.
* This funchtion handles function pointers, including std::endl
*/
inline TLogFile& operator<< (std::ostream&(*func)(std::ostream&)){
(*stream) << func;
return *this;
}
/* should handle everything else */
template<typename T>
inline TLogFile& operator<< (const T& t) {
(*stream) << t;
return *this;
}
}
See it working in online compiler
This way your objects' operator<<s should be able to take anything that std::ostream's can take.
Edit:
Next time, please say that you want to have custom std::endl.
I'm not sure that function with signature
inline TLogFile& operator<< (std::ostream&(*func)(std::ostream&))
is used only when std::endl is passed to it. My previous solution seems inelegent or even inworking. I'm wondering about how to change behaviour of std::endl when it's passed to object of different class.
Notes:
In most cases I'd like to use '\n instead of std::endl.
TLogFile* log = new TLogFile("some arguments...");
I think using raw pointer isn't the best idea here (it's easy to forget about delete),
unless you have to explicitly decide when the object should die.
When the object should die when the current scope does, it should be a local variable:
TLogFile log("some arguments...");
//Usage:
log << "Hello world."; // (1)
log << "Hello world." << endl; // (2)
log << std::hex << setw(2) << setfill('0') << someValue << endl; // (3)
If the object is used in multiple places, and each of the places uses it independently from others, IMO the best solution is to use std::shared_ptr:
#include <memory>
#include <utility>
auto log=std::make_shared<TLogFile>("some arguments...");
//Usage:
*log << "Hello world."; // (1)
*log << "Hello world." << endl; // (2)
*log << std::hex << setw(2) << setfill('0') << someValue << endl; // (3)
This way the object dies when the last shared_ptr does.
I used pointer in the class to be able to re-assign it. If you don't need re-assignment, you can use reference instead.
Thanks to GingerPlusPlus. I found out, that the operator operator<< (std::ostream&(*func)(std::ostream&)) is called only once for the endl (maybe this assumtion is not always true, Please read remarks/edit above of GingerPlusPlus). I replaced the ostream against a stringstream and write the contens of the stringstream when the operator ist called.
class TLogFile{
protected:
std::ostream* stream;
std::stringstream line;
public:
/* default ctor, copy ctor and assignment operator: */
TLogFile(std::ostream& _stream=std::clog):stream(&_stream){}
TLogFile (const TLogFile&) =default;
TLogFile& operator= (const TLogFile&) =default;
void write() {
// Doing some write stuff
// ...
// Empty stringstream buffer
line.str(std::string());
}
/* std::endl is overloaded,
* so I think compiler doesn't know which version to use.
* This funchtion handles function pointers, including std::endl
*/
inline TLogFile& operator<< (std::ostream&(*func)(std::ostream&)){
line << func;
write();
return *this;
}
/* should handle everything else */
template<typename T>
inline TLogFile& operator<< (const T& t) {
line << t;
return *this;
}
}

Resources