If you run the following C++ codes in both MSVC debug and release configuration. You can get different gCounter result. See below.
#include <stdio.h>
int gCounter = 0;
class Test
{
public:
Test()
{
printf("constructor\n");
gCounter++;
}
Test( const Test& )
{
printf("copy constructor\n");
gCounter++;
}
Test( Test&& )
{
printf("move constructor\n");
gCounter++;
}
Test& operator=( Test& )
{
printf("assignment\n");
gCounter++;
}
Test& operator=( Test&& )
{
printf("move assignment\n");
gCounter++;
}
~Test() {}
};
Test case1()
{
Test t = Test();
return t;
}
int main()
{
case1();
printf( "%d\n", gCounter );
return 0;
}
Debug Result:
constructor
move constructor
2
Release Result:
constructor
1
I am surprise to see the result is different. Is it expected behavior? Does it lead to a big issue, if put some critical logical within move constructor? Is there anyone can help?
Related
I have some struct like this:
struct A { ... };
struct B { ... };
And I have a template like this:
template<typename struct_arg>
class X { ... }
Now I wanna create an array of arguments as struct like this:
args [2] { A, B };
for (args) {
X<args[i]> x;
}
Can I possible to create an array like this!?
Yes, you can do. std::variant is made for this usage and you can access such members of a variant with std::visit.
But if you do so, keep in mind, that each element of the array has an additional data member which has the type information and that each element has at minimum the size of the largest type you store. And also std::visit comes with a overhead, as a table for access the data member must be created. Typically done in compile time, but sometime g++ generates it in run time, which will decrease speed a lot!
struct A
{
void Do() { std::cout << "A" << std::endl; }
};
struct B
{
void Do() { std::cout << "B" << std::endl; }
};
int main()
{
std::array<std::variant< A,B >,2> arr{ A{}, B{}, B{}, A{} };
for ( auto& element: arr )
{
std::visit( []( auto& vari ) { vari.Do(); }, element );
}
}
Or if you like your encapsulation with an additional strucuture/class like given in your example:
struct A
{
void Do() { std::cout << "A" << std::endl; }
};
struct B
{
void Do() { std::cout << "B" << std::endl; }
};
template < typename struct_arg >
struct X: public struct_arg{};
int main()
{
std::array<std::variant< X<A>,X<B> >,2> arr{ X<A>{}, X<B>{} };
for ( auto& element: arr )
{
std::visit( []( auto& vari ) { vari.Do(); }, element );
}
}
I need to create a queue of different class objects (These classes are not related). I found a solution as follows:
Create a base class and use polymorphism.
Here is how I implemented it,
class Task {
public:
virtual void operator()() {
printf("should not be called\n");
}
};
class TaskRPCB : public Task {
private:
int x;
// other varibles
std::function<void(int)> func;
public:
TaskRPCB(std::function<void(int)>&f , int x) {
this->func = f;
this->x = x;
}
void operator()() {
printf("TaskRPCB function is executing...\n");
func(x);
}
};
class TaskECB : public Task {
private:
// other varibles
std::function<void(void)> func;
public:
TaskECB(std::function<void(void)>&f) : func(f) {}
void operator()() {
printf("TaskECB function is executing...\n");
func();
}
};
void F1() { // dummy function for example
cout <<"no x"<<endl;
}
void F2(int x) { // dummy function for example
cout <<"x : "<<x<<endl;
}
int main() {
queue<unique_ptr<Task>> Q;
function<void()> func1 = F1;
function<void(int)> func2 = F2;
TaskECB task1(func1);
TaskRPCB task2(func2,4);
Q.emplace(new TaskECB(func1));
Q.emplace(new TaskRPCB(func2,4));
(*Q.front())();
Q.pop();
(*Q.front())();
Q.pop();
}
The problem is, I can not push the objects directly as shown above. I have to create an object of an inherited class and pass it to another function to do the push action. It is because ( in my case ) the queue is a part of a thread-safe queue and it has separate Push() method.
template<typename T>
void threadSafeQueue<T>::Push(T newData) { /* TODO: size check before pushing */
std::shared_ptr<T> data(std::make_shared<T>(std::move(newData)));
/* construct the object before lock*/
std::lock_guard<std::mutex> lk(mut);
taskQueue.push(data);
dataCond.notify_one();
}
Earlier I did not have multiple tasks to execute ( or push ) into the queue, therefore
threadSafeQueue<TaskRPCB> workQ declaration worked fine for me.
Creating a base Task class like above is not working because of object slicing
Can you suggest other ways to store objects in the queue ( so that I can still use the lock guarded Push() method )
Thanks !
update :
is the correct way of using variant?
typedef std::variant<TaskECB, TaskRPCB> myType;
int main() {
queue<unique_ptr<myType>> Q;
function<void()> func1 = F1;
function<void(int)> func2 = F2;
TaskECB task1(func1);
TaskRPCB task2(func2,4);
myType x = task1;
Q.push(make_unique<myType>(x));
x = task2;
Q.push(make_unique<myType>(x));
if((*Q.front()).index() == 0) {
auto f1 = get<TaskECB>(*Q.front());
f1();
Q.pop();
}
if((*Q.front()).index() == 1) {
auto f1 = get<TaskRPCB>(*Q.front());
f1();
Q.pop();
}
}
update2:
using myVariantType = std::variant<TaskECB, TaskRPCB>;
struct VisitPackage {
void operator()(TaskECB & task) {
task();
}
void operator()(TaskRPCB& task) {
task();
}
};
int main() {
queue<myVariantType> Q;
function<void()> func1 = F1;
function<void(int)> func2 = F2;
TaskECB task1(func1);
TaskRPCB task2(func2,4);
Q.emplace(task1);
Q.emplace(task2);
std::visit(VisitPackage(), Q.front());
Q.pop();
std::visit(VisitPackage(), Q.front());
Q.pop();
}
I am trying to get the return type of a function that I bind in. In this instance I was expecting to see the return type of GetFactorialResult (int).
#include <iostream>
#include <boost/core/demangle.hpp>
#include <typeinfo>
namespace
{
const int testNumber = 10;
int GetFactorialResult(int number)
{
if (number > 1)
{
return number * GetFactorialResult(number - 1);
}
else
{
return 1;
}
}
template <typename Func, typename... Args>
void Submit(Func&& func, Args&&... args)
{
auto boundTask = std::bind(std::forward<Func>(func), std::forward<Args>(args)...);
using ResultType = typename std::result_of<decltype(boundTask)()>::type;
char const * name = typeid( ResultType ).name();
std::cout << boost::core::demangle( name ) << std::endl;
}
}
int main()
{
Submit([](int number)
{
GetFactorialResult(number);
}, number);
return 0;
}
Output
void
0
When I print the type of boundTask, I see what I expect:
std::_Bind<\main::{lambda(int)#1} (int)> (the backslash doesnt
exist, but couldnt figure out how to display it without it).
I assume I am getting void because of I'm doing decltype(boundTask)(), but if I remove the parenthesis, it fails to compile.
I only have access to c++11 features.
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.
In g++ I could do this:
struct s
{
int a, b;
};
void MyFunction(s) { }
int main()
{
MyFunction((s) { 0, 0 });
return 0;
}
In Visual Studio however, it doesn't work. is there any way to make it work or some alternative syntax without making a variable and initializing it (and without adding a constructor to the struct as it will make it non-aggregate and it wouldn't be able to initialize in aggregates)?
My C is a bit rusty, but didn't you have to use struct s unless you typedef it? Something like this:
struct s
{
int a, b;
};
void MyFunction(struct s) { }
int main()
{
MyFunction((struct s) { 0, 0 });
return 0;
}
or
typedef struct s
{
int a, b;
} s_t;
void MyFunction(s_t) { }
int main()
{
MyFunction((s_t) { 0, 0 });
return 0;
}