I am trying to write a wrapper for std::thread with a run method , which will allow thread to execute only once run is called.
class ThreadRAII_WITHRUN {
public:
enum class DtorAction { join, detach };
template< class Function, class... Args >
ThreadRAII_WITHRUN(DtorAction a,Function&& f, Args&&... args)
: action(a)
, t(std::thread([&](){pro.get_future().wait(); std::forward<Function>(f)(std::forward<Args>(args)...);}))
{
}
void run()
{
pro.set_value();
}
~ThreadRAII_WITHRUN()
{
if (t.joinable()) { // joinability test
if (action == DtorAction::join) {
t.join();
} else {
t.detach();
}
}
}
ThreadRAII_WITHRUN(ThreadRAII_WITHRUN&&) = default; // support
ThreadRAII_WITHRUN& operator=(ThreadRAII_WITHRUN&&) = default; // moving
std::thread& get() { return t; }
private: // as before
DtorAction action;
std::promise<void> pro;
std::thread t;
};
This code compiles with gcc6.1.0 but not with gcc4.8.5
with gcc4.8.5 with -std=c++11 flag I get below error.
g++ -std=c++11 thread.cpp -pthread
thread.cpp: In lambda function:
thread.cpp:74:94: error: parameter packs not expanded with â...â:
, t(std::thread([&](){pro.get_future().wait(); std::forward<Function>(f)(std::forward<Args>(args)...);}))
^
thread.cpp:74:94: note: âargsâ
thread.cpp: In instantiation of âstruct ThreadRAII_WITHRUN::ThreadRAII_WITHRUN(ThreadRAII_WITHRUN::DtorAction, Function&&, Args&& ...) [with Function = threadwithraii_run()::__lambda10; Args = {int}]::__lambda9â:
thread.cpp:74:106: required from âThreadRAII_WITHRUN::ThreadRAII_WITHRUN(ThreadRAII_WITHRUN::DtorAction, Function&&, Args&& ...) [with Function = threadwithraii_run()::__lambda10; Args = {int}]â
thread.cpp:104:117: required from here
thread.cpp:74:94: error: using invalid field âThreadRAII_WITHRUN::ThreadRAII_WITHRUN(ThreadRAII_WITHRUN::DtorAction, Function&&, Args&& ...)::__lambda9::__argsâ
does anyboday know the reason for the same?
A bit off-topic, that lambda captures constructor arguments by references. By the time run is called some or all of these references may have become invalid. Capturing arguments by value may be safer, e.g.:
std::thread([=](){ ... }))
^
|
capture by value
Related
I'm trying to understand how the compiler handles this code. The two class methods both reference the enumeration before it is defined, but only one generates a compile error. I'm using GCC 9.2:
class Test {
public:
Test() {}
~Test(){}
//gcc seems to be happy with this...
int Foo()
{
TestState v = TestState::Value1;
if (v == TestState::Value1) {
return 0;
} else if (v == TestState::Value2) {
return 1;
}
}
// ... but it doesn't work when used as a parameter
int Bar(TestState v)
{
if (v == TestState::Value1) {
return 0;
} else if (v == TestState::Value2) {
return 1;
}
}
private:
enum class TestState:bool
{
Value1 = false,
Value2 = true
};
};
In this case, the function Foo compiles fine under gcc 9.2, but Bar does not:
enum.cpp:18:13: error: ‘TestState’ has not been declared
int Bar(TestState v)
^
enum.cpp: In member function ‘int Test::Bar(int)’:
enum.cpp:20:13: error: no match for ‘operator==’ (operand types are ‘int’ and ‘Test::TestState’)
if (v == TestState::Value1) {
^
enum.cpp:22:20: error: no match for ‘operator==’ (operand types are ‘int’ and ‘Test::TestState’)
} else if (v == TestState::Value2) {
Why does gcc seem to accept the usage of the enum prior to definition in one instance but not another? I understand that the enum should be declared before these functions, but why does Foo compile without error?
Maybe you can see this as a lack of declaration of TestState by the time Bar(TestState) is declared. Actually this code can be simplified as below:
struct A {
void f() {} /// fine
void g(B) {} /// not fine
struct B {};
};
int main() {
return 0;
}
This code just can't compile as yours, since by the time g(B) is declared, the compiler needs to look up where the declaration of B is, which cannot be found.
That's when we need Forward Declaration. Add a forward declaration, and you may find compilation successful:
struct A {
void f() {} /// fine
struct B;
void g(B) {} /// fine now
struct B {};
};
int main() {
return 0;
}
It's the same with your code. So add private: enum class TestState : bool; before the public in your code, and it'll compile.
I have the following c++ code
#include <iostream>
template<typename Func>
class Foo
{
private:
Func func;
public:
Foo(Func func) : func(func) {}
template<typename T>
Func wrap()
{
Func clbk = func;
auto wrapperCB = [clbk](T t) {
auto job = [clbk, t](){
clbk(t);
};
job();
};
return wrapperCB;
}
template<typename T>
void call(T t)
{
func(t);
}
};
int main()
{
int m = 2;
auto f = [](int & p) {std::cout << "test success " << p << "\n";};
auto obj = std::make_shared<Foo<std::function<void(int &)>>>(f);
auto wrapper = obj->template wrap<int &>();
wrapper(m);
return 0;
}
This is giving compilation error
tsavs-mbp:p utsagarw$ clear; g++ -std=c++11 a.cpp -o z; ./z
a.cpp:18:17: error: no matching function for call to object of type 'const std::__1::function<void (int &)>'
clbk(t);
^~~~
a.cpp:38:32: note: in instantiation of function template specialization 'Foo<std::__1::function<void (int &)> >::wrap<int &>' requested here
auto wrapper = obj->template wrap<int &>();
^
/Applications/Xcode_10.1/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/functional:1677:9: note: candidate function not viable: 1st argument ('const int') would lose const qualifier
_Rp operator()(_ArgTypes...) const;
^
1 error generated.
I don't understand this error. Where did this const come from?
It is building successfully if in wrap I don't create job functor and call clbk directly. What is this job doing to type T?
template<typename T>
Func wrap()
{
Func clbk = func;
auto wrapperCB = [clbk](T t) {
clbk(t);
};
return wrapperCB;
}
If you want to modify any captured variable inside lambda you have to specify it as mutable.
t variable is captured by copy, so you can only read it:
auto job = [clbk, t]() // <-- t passed by copy
{
clbk(t); // clbk takes t by reference -> int&
};
your callback, clbk has signature int& so it means it could modify t. What is not allowed.
Solution:
auto job = [clbk, t]() mutable // keyword 'mutable' added
{
clbk(t); // clbk can change t
};
or make function taking const int& as parameter - then t can be only read.
Demo
How to pass lambda as template parameter.
For example this code
template<void (*callback)()>
void function() {
callback();
}
int main() {
function<[]() -> void { std::cout << "Hello world\n"; }>();
}
fails with error "invalid template argument for 'function', expected compile-time constant expression".
What I'm doing wrong.
Edit
I want to implement something like this
template<typename T,
T (*deserializer)(buffer *data),
void (*serializer)(T item, buffer *data)>
class Type {
public:
T item;
Type(T item) : item(item) {
}
Type(buffer *data) {
deserialize(data);
}
void serialize(buffer *data) {
serializer(item, data);
}
void deserialize(buffer *data) {
deserializer(data);
}
};
typedef Type<int, [](buffer* data) -> int { return -1; }, [](int item, buffer* data) -> void {}> IntType
typedef Type<long, [](buffer* data) -> long { return -1; }, [](long item, buffer* data) -> void {}> LongType
Lambdas in C++14, including their conversion to function pointers, are not constexpr.
In C++17, this is going to change. There are no stable compilers with that feature implemented that I'm aware of (if you find one, can you mention it in the comments below?).
At that point
constexpr auto tmp = []() -> void { std::cout << "Hello world\n"; };
function<+tmp>();
will definitely work. I am uncertain if
function<+[]() -> void { std::cout << "Hello world\n"; }>()
would work; there are some rules about lambdas in unevaluated contexts and inside template argument lists that may be separate from the constexpr lambda problem and may apply here.
We can hack it in C++14.
Create a template class that stores a static copy of a lambda and exposes a static function with the same signature (f_ptr) that calls that static copy of a lambda.
Instantiate it once globally with your lambda.
Pass a pointer to the f_ptr to your template.
So:
template<class L> struct stateless; // todo
template<class L> stateless<L> make_stateless(L l){return std::move(l);}
auto foo = make_stateless( []() -> void { std::cout << "Hello world\n"; } );
function< &foo::f_ptr >();
this is almost certainly not what you want.
The kind of template in the example does not take a type as a parameter, but rather a value. This value needs to be determinable at runtime, in order to instantiate the template, and the value of a lambda is not a compile time constant, so this method just wont do. The common way of sending functors to a function is:
template<typename Func>
void foo(Func&& f)
{
f();
}
And since you want a class template (please put such information in the question, not the comments), here is an example using classes:
#include <utility>
template<typename Func>
class MyClass
{
public:
MyClass(Func&& f) : f(f) {}
void Run() { f(); }
private:
Func f;
};
template<typename Func>
MyClass<Func> MakeMyClass(Func&& f)
{
return { std::forward<Func>(f) };
}
int main()
{
auto x = MakeMyClass( [](){} );
x.Run();
}
I found a problem that I guess is due to a bug in GCC.
Anyway, before opening an issue, I would like to be sure.
Consider the code below:
#include<algorithm>
#include<list>
template<typename U>
struct S {
using FT = void(*)();
struct T { FT func; };
template<typename>
static void f() { }
std::list<T> l{ { &f<int> }, { &f<char> } };
void run() {
l.remove_if([](const T &t) { return t.func == &f<int>; }); // (1)
l.remove_if([](const auto &t) { return t.func == &f<int>; }); // (2)
}
};
int main() {
S<void> s;
s.run();
}
clang v3.9 compiles both (1) and (2) as expected.
GCC v6.2 compiles (1), but it doesn't compile (2).
The returned error is:
error: 'f' was not declared in this scope
Moreover, note that GCC compiles (2) if it is modified as it follows:
l.remove_if([](const auto &t) { return t.func == &S<U>::f<int>; }); // (2)
As far as I know, using an const auto & instead of const T & should not alter the behavior in this case.
Is it a bug of GCC?
Per [expr.prim.lambda]:
8 - [...] [For] purposes of name lookup (3.4) [...] the compound-statement is considered in the context of the lambda-expression. [...]
MCVE:
template<int>
struct S {
template<int> static void f();
S() { void(*g)(char) = [](auto) { f<0>; }; }
};
S<0> s;
Hoisting the compound-statement to the context of the lambda-expression gives a clearly valid program:
template<int>
struct S {
template<int> static void f();
S() { f<0>; }
};
S<0> s;
So yes, this is a bug in gcc.
I wanted to store a vector of function pointers, each taking different no. of arguments in a class "Store". So, wrote a templated class "Func" that would store the function as a std::function and its arguments in a tuple.
I derived this "Func" class from a non-template base class "IFunc", so that i can store a vector of pointers to this base class in the class "Store".
template<typename... Args>
class Func : public IFunc
{
public:
std::function<void (Args...)> f;
std::tuple<Args...> args;
template <typename F,typename... Ar>
Func(F&& func,Ar&&... arg): f(std::forward<F>(func)),args(std::make_tuple(std::forward<Ar>(arg)...))
{
}
virtual ~NonMemfun()
{
}
//other methods to unpack the tuple and call the function
};
The IFunc class:
class IFunc
{
public:
Ifunc(){}
virtual ~Ifunc(){}
};
The Store class:
class Store
{
std::vector<Ifunc*> funcs;
public:
template<typename... Args,typename... Args2>
void registerfunc(std::string name,int runs,void(*f)(Args...),Args2&&... arg)
{
Func<Args2...>* sample = new Func<Args2...>(f,arg...);
Ifunc* fp = sample;
funcs.push_back(fp);
}
};
I want to iterate through the vector and call each function. To do that i need to do a static cast like this:
Func<>* der = static_cast<Func<>*>(funcs[0]);
When i try to do this, the cast doesn't happen properly. I cannot specify the template paramenters(variadics) since this class(Store) is not aware of them.
I am totally stuck at this place. Something is wrong with my design i guess. Can someone please suggest me a better way to do this. Thank you.
Rather than trying to do a cast from IFunc to Func<>, you should make a pure virtual function, Apply() in IFunc, which Func<> defines as apply(f, args...);. As you iterate over the vector of IFunc pointers, simply call IFunc->Apply(), which will dispatch to the Func<>::Apply() and do the actual apply.
I'm not much of a C++ programmer, but I think you may find this useful.
I'm sure you know that templates are a compile time thing in C++ so your functions need to be known at build time.
With that said, if you do know your functions and you just want to map them to say a string command and then dynamically bind arguments from something like a stream then this code should help you. It is actually able to use a dynamic_cast to retrieve the command from the map.
this snippet is from a school project I did a while back that had a similar goal:
#include <map>
#include <string>
#include <sstream>
#include <tuple>
using namespace std;
class Shell {
class Command {
public:
virtual ~Command() {};
virtual void executeWithArgStream(Shell*, istream& s)=0;
};
template <typename... ArgTypes>
class ShellCommand : public Command {
private:
// FIXME: its probably more apropriate for FuncType to return an int for exit code...
typedef function<void(Shell*, ArgTypes...)> FuncType;
FuncType _f;
tuple<ArgTypes...> args;
template<int... Is>
struct seq { };
template<int N, int... Is>
struct gen_seq : gen_seq<N - 1, N - 1, Is...> { };
template<int... Is>
struct gen_seq<0, Is...> : seq<Is...> { typedef seq<Is...> type; };
template<size_t I = 0, class ...P>
typename std::enable_if<I == sizeof...(P)>::type
// template for functions with no arguments
parseArgs(istream& is, std::tuple<P...> &) {}
template<size_t I = 0, class ...P>
typename std::enable_if<I < sizeof...(P)>::type
parseArgs(istream& is, std::tuple<P...> & parts) {
// this is the magic bit that takes a tuple of pointers (representing the command arguments)
// created at compile time and creates new instances of each argument type and populates it from
// the given input stream :D
auto& part = std::get<I>(args);
// hmmm should we delete or recycle...
delete part;
part = new typeof(*part);
is >> *part;
parseArgs<I + 1>(is, parts);
}
template<int ...S>
void callFunc(Shell* shell, seq<S...>) {
_f(shell, get<S>(args) ...);
}
public:
static constexpr size_t numArgs = sizeof...(ArgTypes);
ShellCommand(FuncType f) : _f(f) {};
void operator()(Shell* shell, ArgTypes... args) {
_f(shell, args...);
};
void executeWithArgStream(Shell* shell, istream& s)
{
parseArgs(s, args);
callFunc(shell, typename gen_seq<sizeof...(ArgTypes)>::type());
};
};
private:
typedef shared_ptr<Command> CommandPtr;
typedef map<string, CommandPtr> FMap;
FMap _cmdMap;
ostream& _out;
istream& _in;
public:
Shell(istream& is = cin, ostream& os = cout)
: _out(os), _in(is)
{
// populate
_cmdMap.insert(pair<string, CommandPtr>("chdir", make_shared<ShellCommand<string*>>(&Shell::chdir)));
_cmdMap.insert(pair<string, CommandPtr>("list", make_shared<ShellCommand<>>(&Shell::list)));
_cmdMap.insert(pair<string, CommandPtr>("count", make_shared<ShellCommand<>>(&Shell::count)));
};
int run();
// FIXME: its probably more apropriate for execute to return an int for exit code...
template <typename... ArgTypes>
void execute(string& command, ArgTypes... args);
void executeWithArgStream(string& command, istream& istr);
// shell commands:
// any command parameters must be done as a pointer!
// the magic that parses string arguments into real types depends on it!
void list() {
list command
};
void chdir(string* dir) {
// chdir command
};
void count() {
// count command
};
};
template <typename... ArgTypes>
void Shell::execute(string& command, ArgTypes... args)
{
typedef ShellCommand<ArgTypes...> CommandType;
CommandType* c = dynamic_cast<CommandType*>(_cmdMap[command].get());
// TODO: neeed to diferentiate between invalid commands and some kind of dynamic_cast failure
if (c) {
(*c)(this, args...);
} else {
// dynamic cast failure
throw runtime_error("Broken Implementation for:" + command);
}
}
void Shell::executeWithArgStream(string& command, istream& istr)
{
Command* c = _cmdMap[command].get();
if (c) {
c->executeWithArgStream(this, istr);
} else {
throw runtime_error("Invalid Shell Command: " + command);
}
}
int Shell::run()
{
do {
string cmd, argString;
_out << _currentDir->name() << "> ";
_in.clear();
_in >> cmd;
if (cmd == "q") {
return 0;
}
if (_in.peek() == ' ')
_in.ignore(1, ' ');
getline(cin, argString);
if (_cmdMap[cmd]) {
try {
if (argString.length()) {
istringstream s(argString);
executeWithArgStream(cmd, s);
} else {
execute(cmd);
}
} catch (runtime_error& e) {
_out << e.what() << endl;
}
} else {
_out << "unrecognized command: " << cmd << endl;
}
} while (true);
}
int main(int argc, const char * argv[])
{
// start the interactive "shell"
Shell shell();
return shell.run();
}