C++11: How is boost::make_tuple different from std::make_tuple? - c++

http://en.cppreference.com/w/cpp/utility/tuple/make_tuple
(for convenience code is pasted)
#include <iostream>
#include <tuple>
#include <functional>
std::tuple<int, int> f() // this function returns multiple values
{
int x = 5;
return std::make_tuple(x, 7); // return {x,7}; in C++17
}
int main()
{
// heterogeneous tuple construction
int n = 1;
auto t = std::make_tuple(10, "Test", 3.14, std::ref(n), n);
n = 7;
std::cout << "The value of t is " << "("
<< std::get<0>(t) << ", " << std::get<1>(t) << ", "
<< std::get<2>(t) << ", " << std::get<3>(t) << ", "
<< std::get<4>(t) << ")\n";
// function returning multiple values
int a, b;
std::tie(a, b) = f();
std::cout << a << " " << b << "\n";
}
https://theboostcpplibraries.com/boost.tuple
#include <boost/tuple/tuple.hpp>
#include <boost/tuple/tuple_io.hpp>
#include <string>
#include <iostream>
int main()
{
typedef boost::tuple<std::string, int, bool> animal;
animal a = boost::make_tuple("cat", 4, true);
a.get<0>() = "dog";
std::cout << std::boolalpha << a << '\n';
}
It would seem based on the documentation that boost::make_tuple and std::make_tuple are exactly interchangeable.
Are they really exactly interchangeable? In what circumstances are they not?
In the boost documentation it says that boost::tuple and std::tuple are the same in c++11
In the std documentation it says make_tuple returns a std::tuple.
So are there any nuances that I am missing?

There's no functional difference.
boost::tuple was created almost two decades ago, and std::tuple was introduced to the core Standard Library in C++11, in 2011, only 6 years ago.
They're not "interchangable", for a given definition of the term "interchangable". You can't assign a std::tuple<> to a boost::tuple<> or vice-versa, because even if their implementation is the same, they still represent distinct objects.
However, because they are essentially the same, you can do a find→replace for boost::tuple→std::tuple and more-or-less arrive with identically behaving and performing code, and because dependency on the boost libraries is not something every programmer can have, it's almost universally recommended that any project which has access to >=C++11 prefer std::tuple in all cases.
EDIT:
As pointed out by #Nir, there are a few syntactical differences between boost::tuple and std::tuple, notably involving the get<>() syntax, which is also a member function of boost::tuple and only a free function for std::tuple.

Related

How can I have a C++ set with more than 1 data type?

Trying to learn C++ coming from Python, and in python a set can have multiple types. How do I do this in C++? I'm specifically trying to have a set with both integers and strings. For example:
#include <set>
#include <string>
using namespace std;
int main() {
set<int, string> s;
s.insert(1);
s.insert("string");
}
Having multiple types of elements in a container is called a heterogenous container.
C++ supports this from C++17 using std::any which can hold any type, or as EOF said using std::variant when you want to define the set of possible types yourself.
Here is a demo of std::any using std::any_cast:
#include <any>
#include <iostream>
#include <list>
#include <map>
#include <set>
int main()
{
std::list<std::any> any_list;
int myInt = 1;
std::string myString("I'm a string");
using MapType = std::map<std::list<int>, std::string>;
MapType myMap;
struct CustomType {
void* pointer;
};
any_list.emplace_back(std::any());
any_list.emplace_back(myInt);
any_list.emplace_back(myString);
any_list.emplace_back(myMap);
any_list.emplace_back(CustomType());
// To show the awesome power of std::any we add
// the list as an element of itself:
any_list.emplace_back(any_list);
for(auto& element: any_list) {
if(!element.has_value()) {
std::cout << "Element does not hold a value" << std::endl;
continue;
}
if (int* someInt = std::any_cast<int>(&element)) {
std::cout << "Element is int: " << *someInt << '\n';
} else if (std::string* s = std::any_cast<std::string>(&element)) {
std::cout << "Element is a std::string: " << *s << '\n';
} else if (std::any_cast<MapType>(&element)) {
std::cout << "Element is of type MapType\n";
} else if (std::any_cast<CustomType>(&element)) {
std::cout << "Element is of type CustomType\n";
} else {
std::cout << "Element is of unknown but very powerful type\n";
}
}
}
This yields output:
Element does not hold a value
Element is int: 1
Element is a std::string: I'm a string
Element is of type MapType
Element is of type CustomType
Element is of unknown but very powerful type
The pre-C++17 method of doing this is obviously a struct with manual type info and void*.
Note that I used std::list instead of std::set because std::any does not have operator< defined by default. This could be solved by defining your own comparison predicate.
My personal opinion is that usually when you think you want to use a heterogenous container it's worth re-evaluating your design and stick to normal homogenous containers, but it's there if you need it :-)

How can I use C++11 parameter packs to distinguish between compile time constants and runtime vars?

I am trying to make an optimal function that would accept compile-time constants and runtime constants, and do optimization at compile-time when the compiler knows the value. The problem is when I try to unpack the parameter pack it has to be moved into a runtime variable causing the compiler not to optimize in the same manner as if the constants was properly propagated. Unfortunately I'm not quite sure how to unpack to a single object while maintaining a mixture of compile-time and runtime variables in the same structure.
I have two working test cases: one that does what it suppose to do (assembly-wise), but is not generic with regards to parameter packs. The other does have a parameter packs, but the compiler loses the compile-time constant through the unpacking.
// Example program
#include <iostream>
#include <string>
#include <type_traits>
#include <functional>
#include <tuple>
struct ii{
int value;
};
template<int Val>
using tt = std::conditional_t<Val==0, ii, std::integral_constant<int, Val> >;
template<int... vals>
void foo( tt<vals>... inp)
{
const int arr[sizeof...(inp)] = {inp.value...};
std::cout << "parameter " << (16 / arr[0]) << std::endl; //<-incorrect asm
std::cout << "parameter " << (16/ arr[1] ) << std::endl; //expected asm
}
void check(ii i, std::integral_constant<int, 4> a)
{
std::cout << "i = " << ( 16 / i.value ) << std::endl; //<--expected asm
std::cout << "i = " << (16 / a.value ) << std::endl; //<--this is OK in asm
}
int main()
{
std::integral_constant<int, 4> four;
check(ii{1},four );
foo<four.value,0>(four, ii{1});
}
The expected results for "(16 / arr[0])" should be calculated at compile time, and it should be a constant 4.
Thank you!

C++ function specialization behaves different for plain types and classes

i have this piece of code (http://coliru.stacked-crooked.com/a/ee05a00fc8ab5057):
#include <type_traits>
struct unregistered;
unregistered register_type(...);
template<class T>
constexpr bool is_registered = !std::is_same_v<unregistered, decltype(register_type(std::declval<T>()))>;
template<class T>
struct test_registration
{
static_assert(is_registered<T>, "Type is not registered!");
};
struct foo{};
struct bar{};
void register_type(int);
void register_type(char);
void register_type(void*);
void register_type(foo);
void register_type(foo*);
#include <boost/core/demangle.hpp>
#include <iostream>
int main()
{
std::cout << boost::core::demangle(typeid(test_registration<foo>).name()) << "\n";
std::cout << boost::core::demangle(typeid(test_registration<foo*>).name()) << "\n";
std::cout << boost::core::demangle(typeid(test_registration<int>).name()) << "\n";
std::cout << boost::core::demangle(typeid(test_registration<char>).name()) << "\n";
std::cout << boost::core::demangle(typeid(test_registration<void*>).name()) << "\n";
std::cout << boost::core::demangle(typeid(test_registration<long>).name()) << "\n";
std::cout << boost::core::demangle(typeid(test_registration<bar>).name()) << "\n";
return 0;
}
The compiler generates errors for the calls using int, char, void*, long and bar.
I expect the errors for long and bar.
What I do not understand is:
Why are int, char, and foo treated differently?
Why are void*, and foo* treated differently? (both are ptrs)
I assume the reason has to do with foo beeing class type and int and char beeing plain types.
I would like to know the reason. Is it a compiler bug or is there some passage in the standard explaining this behaviour?
What I am asking is not how I can fix this problem (see link to coliru for a fix).
What I want to know is why it is behaving like this.

Printing map values with only STL loops

i'm having a problem where i can't see what to do. I have to print map values with only STL loops, i can't use for loops while loops etc..
here's my map std::map<std::string, Borrowed*> map;
I'd rather not declare another function myself unless if it's really necessary to do that
Edit: I tried using for_each and copy function but if that's what you should use i don't see how you would use them
Just use std::for_each with a lambda that prints the element (using a map<string, int> for simplicitly, use your own code for printing Borrowed* elements).
#include <algorithm>
#include <iostream>
#include <iterator>
#include <map>
int main()
{
std::map<std::string, int> m = { { "bla", 1 }, { "yada", 2 } };
std::for_each(m.begin(), m.end(), [](auto const& elem) {
std::cout << "{ " << elem.first << ", " << elem.second << "}, ";
});
}
Live Example
Note this uses C++14 generalized lambdas (with auto to deduce the parameter type). In C++11 you'd have to explicitly write that out, and in C++98 you'd have to write your own function object to the lambda's work.
Assuming you mean STL algorithms:
Here is a std::for_each example (c++11):
#include <algorithm>
#include <iostream>
std::for_each(map.cbegin(), map.cend(),
[&](const std::pair<std::string, Borrowed*> &pair) {
std::cout << pair.first // std::string (key)
<< " " << pair.second->XXX // Borrowed* (value) or whatever you want to print here
<< "\n";
});
http://en.cppreference.com/w/cpp/algorithm/for_each

can boost::bind be used with references without copying?

Following code shows that the parameter, passed by reference, is copied when using boost::bind. Is there a way to prevent the copying without resorting to pointers (which I currently use as workaround)? (tested with gcc 4.4.3)
#include <iostream>
#include <boost/function.hpp>
#include <boost/bind.hpp>
void function1(int& x)
{
std::cout << "function1 &x: " << &x << std::endl;
}
int main()
{
int y = 0;
std::cout << "main &y: " << &y << std::endl;
boost::function<void()> f = boost::bind(function1, y);
f();
}
You should use boost::ref for passing references to boost bind.
boost::function<void()> f = boost::bind(function1, boost::ref(y));