Using
g++ (Ubuntu 5.4.0-6ubuntu1~16.04.5) 5.4.0 20160609.
I receive the error
slicing.cpp:31:5: error: ‘invoke’ is not a member of ‘std’
slicing.cpp:32:5: error: ‘invoke’ is not a member of ‘std’
When compiling with
g++ -std=c++17 -O2 -g -Wall -c -o slicing.o slicing.cpp
(and the same with -std=gnu++17) code below, modified from Virtual functions and std::function?.
How can I fix this?
I could not find any useful information.
#include <functional>
#include <iostream>
struct base
{
base() {std::cout << "base::base" << std::endl;}
virtual ~base() {std::cout << "base::~base" << std::endl;}
virtual void operator()() {std::cout << "base::operator()" << std::endl;}
};
struct derived1: base
{
derived1() {std::cout << "derived1::derived1" << std::endl;}
virtual ~derived1() {std::cout << "derived1::~derived1" << std::endl;}
virtual void operator()() {std::cout << "derived1::operator()" << std::endl;}
};
struct derived2: base
{
derived2() {std::cout << "derived2::derived2" << std::endl;}
virtual ~derived2() {std::cout << "derived2::~derived2" << std::endl;}
virtual void operator()() {std::cout << "derived2::operator()" << std::endl;}
};
int main(int argc, char* argv[])
{
base* ptr1 = new derived1();
base* ptr2 = new derived2();
std::function<void()> f1 = *ptr1;
std::function<void()> f2(*ptr2);
std::invoke(*ptr1); // calls derived1::operator()
std::invoke(*ptr2); // calls derived2::operator()
//std::invoke(f1); // calls base::operator()
//std::invoke(f2); // calls base::operator()
delete ptr1;
delete ptr2;
return 0;
}
Use the GCC compiler dialect flag -std=c++1z or even better -std=c++17 and upgrade your compiler to GCC 7.
(ed: your compiler seems a bit old so it may not work; notice that GCC 5 was released before the C++17 standard)
With g++ (x86_64-win32-seh-rev1, Built by MinGW-W64 project) 7.2.0
it builds this correctly
#include <iostream>
// C++17
#include <functional>
int Func(int a, int b)
{
return a + b;
}
struct S
{
void operator() (int a)
{
std::cout << a << '\n';
}
};
int main(/*int argc, char* argv[]*/)
{
using namespace std;
std::cout << std::invoke(Func, 10, 20) << '\n'; // 30
std::invoke(S(), 42); // 42
std::invoke([]() { std::cout << "hello\n"; }); // hello
return 0;
}
source: https://www.viva64.com/en/b/0533/#ID0EOHKO
Related
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";}
#include <iostream>
#include <string>
using namespace std;
struct Foo {
virtual ~Foo() = default;
int foo = 321;
};
struct Bar: public Foo {
int bar = 123;
};
int main() {
const Foo* ptr = new Bar();
std::cout << ptr << std::endl;
{
const Bar* ptr = dynamic_cast<const Bar*>(ptr);
std::cout << ptr << std::endl;
}
{
const Bar* ptr2 = dynamic_cast<const Bar*>(ptr);
std::cout << ptr2 << std::endl;
}
return 0;
}
the program output the following lines if compiled with -O2:
0x613c20
0
0x613c20
and if without -O2, it's like:
0x614c20
0x400b70
0x614c20
In both case, the second line seems problematic, when the target variable name conflicts with source variable name of dynamic_cast. I tried both gcc 4.8 and 5.2 and also clang 11.0.3 .
Anyone has clue about this?
I already knew that value of pointer member of class is undefined if it is not initialized in constructor (refer this question). I made a simple example to test it.
main.cc
#include <iostream>
class Foo {
public:
Foo() {
std::cout << __FUNCTION__ << std::endl;
count = 10;
}
void test() {
std::cout << __FUNCTION__ << count << std::endl;
}
private:
int count;
};
class Bar {
public:
void bar() {
std::cout << __FUNCTION__ << std::endl;
std::cout << m_foo << std::endl;
m_foo->test();
m_foo = new Foo();
std::cout << m_foo << std::endl;
}
private:
Foo *m_foo;
};
int main(int argc, char *argv[])
{
std::cout << __FUNCTION__ << std::endl;
Bar bar;
bar.bar();
return 0;
}
If I use g++:
g++ -std=c++11 main.cc -o test
It runs with error as expected:
main
bar
0
Segmentation fault
But, if I change to compile with clang++:
clang++ -std=c++11 main.cc -o test
It runs without any error:
main
bar
0x400920
test-1991643855
Foo
0x1bf6030
As you see, although the pointer is not initialized, it has address not NULL and it can call the function test normally. How can I prevent this error with clang++?
There is no "default value" for pointers. m_foo is not initialized, period. So dereferencing it is undefined behaviour. Be aware that "undefined behaviour" includes "apparently working fine".
Declare m_foo like this:
Foo * m_foo = nullptr;
Dereferencing a nullptr is still undefined behaviour, but on most platforms this will trigger a segmentation fault.
I want to pass a pointer to a class method and call that function from an iterator. The code below fails to compile when I include a derived object.
I've tried using a typename for the class specifier (e.g. TC::*pf) but this doesn't work. Can someone suggest how to make this work?
#include <iostream>
#include <vector>
#include <algorithm>
using std::cout;
using std::endl;
using std::vector;
class Base {
public:
Base(int bval) : bval_(bval) { }
virtual void print() {
cout << "Base: bval:" << bval_ << endl;
}
protected:
int bval_;
};
class Derived : public Base {
Derived(int bval, int dval) : Base(bval), dval_(dval) { }
virtual void print() {
cout << "Derived: bval:" << bval_ << " dval:" << dval_ << endl;
}
private:
int dval_;
};
typedef vector<Base*> MyVecType;
typedef MyVecType::iterator MyVecTypeIter;
template <typename T>
void testFunc(MyVecType& v, T (Base::*pf)()) {
for (MyVecTypeIter iter = v.begin(); iter != v.end(); ++iter) {
((*iter)->*pf)();
}
}
int main() {
MyVecType bvec;
bvec.push_back(new Base(44));
bvec.push_back(new Base(55));
// above compiles and runs ok, but this fails to compile
// with 'no matching function' error:
bvec.push_back(new Derived(66));
testFunc(bvec, &Base::print);
return 0;
}
line
bvec.push_back(new Derived(66));
does not compiler because Derived class constructor is private and is defined to take two int arguments.
Fix that and it will compile and run:
http://cpp.sh/9nrkc
#include <iostream>
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <boost/enable_shared_from_this.hpp>
class A: public boost::enable_shared_from_this<A>
{
typedef boost::function<int()> GET;
public:
A()
{
std::cout << "A::A() " << this << std::endl;
}
~A()
{
std::cout << "A::~A()" << this <<std::endl;
}
void set()
{
myget=boost::bind(&A::get, shared_from_this());
}
Here is the problem: it will not be released when I bind it with with shared_from_this(). But if I bind it with this (boost::bind(&A::get, this)), the instance will be released.
int getI()
{
myget();
}
inline int get()
{
return 1;
}
private:
GET myget;
};
void test()
{
boost::shared_ptr<A> a(new A);
a->set();
a->getI();
}
int main()
{
test();
return 0;
}
My question is: why the instance of A is never released even if the program have been shut down?
The problem is that the myget variable prevents the destructor from ever running.
So you can't even do
~A() {
std::cout << "A::~A()" << this << std::endl;
myget = {};
}
This is what weak-pointers have been invented for. In this particular case though, you could simply use this as there is no way that myget can be accessed after the lifetime of A