using std::apply on std::bind - c++

The following fails to compile with gcc 8.2.0 [stacktrace]
#include <iostream>
#include <tuple>
#include <functional>
void print(int a, int b, int c) {
std::cout << a << ", " << b << ", " << c << std::endl;
}
int main() {
auto b = std::bind(print, 1);
auto t = std::make_tuple(2, 3);
std::apply(b, t);
}
I personally fail to see why, it would seem to be common sense for it to work (in a proper functional language at least).
Could somebody explain the reason it doesn't work?

With std::bind you need to also provide placeholders for the unbound arguments.
auto b = std::bind(print, 1, std::placeholders::_1, std::placeholders::_2);

Related

std::visit with passing pointer fails to compile under clang 13

The following code compiles properly under x64 msvc x19.30 and gcc 11 but fails to compile under clang 13.0.1:
"error: cannot pass object of non-trivial type 'std::shared_ptr<std::pair<int, std::variant<Struct1, Struct2, UnsupportedStruct>>>' through variadic function;"
Does anyone know what the problem is?
The following code produces different outputs depending on passing object:
#include <iostream>
#include <variant>
#include <memory>
struct Struct1{};
struct Struct2{};
struct UnsupportedStruct{};
using VarTypeData = std::variant<Struct1, Struct2, UnsupportedStruct>;
using VarType = std::pair<int, VarTypeData>;
namespace
{
void print(Struct1&, std::shared_ptr<VarType> v) {std::cout << v->first << ": Struct1\n";}
void print(Struct2&, std::shared_ptr<VarType> v) {std::cout << v->first << ": Struct2\n";}
void print(...) {std::cout << "no implementation";}
}
int main()
{
VarType data1 = std::make_pair(100, UnsupportedStruct{});
auto pointerData = std::make_shared<VarType>(data1);
std::visit([&pointerData](auto& c) {print(c, pointerData);}, pointerData->second);
std::cout << std::endl;
pointerData->second = Struct1{};
std::visit([&pointerData](auto& c) {print(c, pointerData);}, pointerData->second);
}
This code works fine for clang after dereferencing:
#include <iostream>
#include <variant>
#include <memory>
struct Struct1{};
struct Struct2{};
struct UnsupportedStruct{};
using VarTypeData = std::variant<Struct1, Struct2, UnsupportedStruct>;
using VarType = std::pair<int, VarTypeData>;
namespace
{
void print(const Struct1&, const VarType& v) {std::cout << v.first << ": Struct1\n";}
void print(const Struct2&, const VarType& v) {std::cout << v.first << ": Struct2\n";}
void print(...) {std::cout << "no implementation";}
}
int main()
{
VarType data1 = std::make_pair(100, UnsupportedStruct{});
auto pointerData = std::make_shared<VarType>(data1);
std::visit([&pointerData](auto& c) {print(c, *pointerData);}, pointerData->second);
std::cout << std::endl;
pointerData->second = Struct1{};
std::visit([&pointerData](auto& c) {print(c, *pointerData);}, pointerData->second);
}
thanks to #康桓瑋 for the answer.
this code does not work for clang, because of
void print(...) {std::cout << "no implementation";}
answer: void print(...) is a C function, where variadic actually means the
's parameter. It accepts only trivial types, which
std::shared_ptr is not. So the behavior is undefined or only
conditionally supported
So, the following changes fix the problem:
template<class... Args>
void print(Args&&...) {std::cout << "no implementation";}

Expand variadic arguments in initializer list fails

I try to create a simple program in which I want to create vector of future arguments.
I created a wrapper function which is used to submit lambda functions and stores internally in a vector the future objects
I use an intermediate step in which I create an initiliazer_list using variadic arguments . But fails to compile. I try to use to call a function in order to push the elements in the vector and fails to compile as well
Below is the code
#include <iostream>
#include <thread>
#include <future>
#include <functional>
#include <cstdlib>
#include <chrono>
#include <initializer_list>
using namespace std;
using FunctPtr = function<int(int, int) >;
using FutureInt = future<int>;
using AsyncVector = vector<FutureInt>;
AsyncVector asyncVec;
template<typename... TemplatePtr>
void submit(TemplatePtr... pFunc)
{
auto initList {pFunc... };
for (auto & element : initList)
{
asyncVec.emplace_back(async(launch::async, element,4,5));
}
}
int main()
{
int a;
int b;
auto addPtr = [](int x, int y)->int
{
std::cout << "add :" << x + y << std::endl;
return x + y;
};
auto multPtr = [](int x, int y)->int
{
std::cout << "mult :" << x * y << std::endl;
return x * y;
};
// submit(add,4,5);
submit(addPtr, multPtr);
for (auto & v : asyncVec)
{
std::cout << "Wait for " << v.get() << std::endl;
}
}
Yes, they are of different types so cannot be in the same init-list easily.
Your best options should probably be:
Either push them all into asyncVec in the same fold-expression.
template<typename... TemplatePtr>
void submit(TemplatePtr... pFunc)
{
(asyncVec.emplace_back(async(launch::async, std::move(pFunc), 4, 5)), ...);
}
Or, if they all are of the same signature, type-erase them, like keeping them in an array of std::function.
template<typename... TemplatePtr>
void submit(TemplatePtr... pFunc)
{
for (auto &&element: {std::function<int(int, int)>(std::move(pFunc))...})
{
asyncVec.emplace_back(async(launch::async, std::move(element), 4, 5));
}
}
(I have specified function signature explicitly though compiler should be able to deduce it.)
Or, if all closures are captureless and of the same signature, simply cast them to the same type when calling submit:
using SameType = int (*)(int, int);
submit(static_cast<SameType>(addPtr), static_cast<SameType>(mulPtr));
This way your original submit should work as is.

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++11: How is boost::make_tuple different from std::make_tuple?

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.

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));