I've got a compiler error but I can't figure out why.
the .hpp:
#ifndef _CGERADE_HPP
#define _CGERADE_HPP
#include "CVektor.hpp"
#include <string>
class CGerade
{
protected:
CVektor o, rv;
public:
CGerade(CVektor n_o, CVektor n_rv);
CVektor getPoint(float t);
string toString();
};
the .cpp:
#include "CGerade.hpp"
CGerade::CGerade(CVektor n_o, CVektor n_rv)
{
o = n_o;
rv = n_rv.getUnitVector();
}
the error message:
CGerade.cpp:10: error: no matching function for call to ‘CVektor::CVektor()’
CVektor.hpp:28: note: candidates are: CVektor::CVektor(float, float, float)
CVektor.hpp:26: note: CVektor::CVektor(bool, float, float, float)
CVektor.hpp:16: note: CVektor::CVektor(const CVektor&)
CGerade.cpp:10: error: no matching function for call to ‘CVektor::CVektor()’
CVektor.hpp:28: note: candidates are: CVektor::CVektor(float, float, float)
CVektor.hpp:26: note: CVektor::CVektor(bool, float, float, float)
CVektor.hpp:16: note: CVektor::CVektor(const CVektor&)
From the looks of it, your CVektor class has no default constructor, which CGerade uses in your constructor:
CGerade::CGerade(CVektor n_o, CVektor n_rv)
{ // <-- by here, all members are constructed
o = n_o;
rv = n_rv.getUnitVector();
}
You could (and probably should) add one, but better is to use the initialization list to initialize members:
CGerade::CGerade(CVektor n_o, CVektor n_rv) :
o(n_o),
rv(n_rv.getUnitVector())
{}
Which specifies how the members are initialized. (And above, it was defaulting to the non-existent default-constructor.)
Your CVektor class has no default constructor (that is, one that takes no arguments), so your CGerade constructor can't call it. Since you're not explicitly calling a CVektor constructor in your initializer list, the compiler implicitly tries to call the default constructor, but there is none to call, so you get an error.
You should explicitly call the CVektor copy constructor using an initializer list:
CGerade::CGerade(CVektor n_o, CVektor n_rv)
: o(n_o), rv(n_rv.getUnitVector())
{
// empty body
}
Related
I have a class MyClass as follows:
class MyClass {
public:
MyClass(vector<vector<float>> arg) {
// some code here
}
MyClass(std::initializer_list<std::initializer_list<float>> arg)
: MyClass(vector<vector<float>>(arg)) {
}
// other class members
};
I'm trying to use a delegating constructor above, as I want an instance of MyClass to be constructed from both std::initializer_list<std::initializer_list<float>> and vector<vector<float>> types, and the constructor code blocks are identical. So I'm trying to delegate the construction of the nested initializer lists by initializing a multidimensional vector and using its constructor.
However, the above code gives me a compiler error:
no instance of constructor "std::__1::vector<_Tp, _Allocator>::vector [with _Tp=std::__1::vector<float, std::__1::allocator<float>>, _Allocator=std::__1::allocator<std::__1::vector<float, std::__1::allocator<float>>>]" matches the argument list -- argument types are: (std::initializer_list<std::initializer_list<float>>)
In file included from /opt/wandbox/gcc-9.3.0/include/c++/9.3.0/vector:67,
from prog.cc:11:
/opt/wandbox/gcc-9.3.0/include/c++/9.3.0/bits/stl_vector.h:622:7: note: candidate: 'std::vector<_Tp, _Alloc>::vector(std::initializer_list<_Tp>, const allocator_type&) [with _Tp = std::vector<float>; _Alloc = std::allocator<std::vector<float> >; std::vector<_Tp, _Alloc>::allocator_type = std::allocator<std::vector<float> >]'
622 | vector(initializer_list<value_type> __l,
| ^~~~~~
/opt/wandbox/gcc-9.3.0/include/c++/9.3.0/bits/stl_vector.h:622:43: note: no known conversion for argument 1 from 'initializer_list<std::initializer_list<float>>' to 'initializer_list<std::vector<float>>'
622 | vector(initializer_list<value_type> __l,
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~
What am I doing wrong here?
The initializer_list constructor for std::vector looks like:
vector(std::initializer_list<value_type>)
Where value_type is the first template argument to std::vector. In this case, std::vector<std::vector<float>> has value_type = std::vector<float> -- which means that it can only be constructed from a std::initializer_list<std::vector<float>> directly.
In order for this to work, you will need to update in one of the following ways:
update your std::initializer_list to be std::initializer_list<std::vector<float>>,
just use the std::vector<std::vector<float>> constructor and ignore using the initializer_list entirely1, or
Range construct from the initializer_list<initializer_list<float>> in the constructor`:
MyClass(std::initializer_list<std::initializer_list<float>> arg)
: vec{arg.begin(), arg.end()}
{
// each iterator points to an initializer_list, which implicitly
// constructs each vector
}
Edit: Since this question is asking with respect to delegating constructors, you would be stuck explicitly constructing a temporary vector-of-vectors first:
MyClass(std::initializer_list<std::initializer_list<float>> arg)
: MyClass{std::vector<std::vector<float>>{arg.begin(), arg.end()}}
This is a case where delegating constructors probably aren't the best solution to your problem. See below.
1 Since std::vector already works properly with initializer lists, even when nested in other types, it would probably be easiest to just ignore adding an explicit std::initializer_list constructor entirely -- and just use move semantics properly in the implementation.
If you're using std::move properly, this constructor should be relatively cheap anyway -- which could make the initializer list functionality come for free.
You need vector of floats in std::initializer_list;
I believe this is what you are looking for
class MyClass{
public:
MyClass(vector<vector<float>> arg ): vec( arg) {
// some code here
}
MyClass(std::initializer_list<std::vector<float>> arg)
: vec( arg ) {};
// other class members
private:
std::vector<vector<float>> vec;
};
Let's have this code using gmock 1.8:
#include "gtest/gtest.h"
#include "gmock/gmock.h"
#include <variant>
class Obj {
public:
MOCK_METHOD0( mock, void() );//<-!!!
};
using Variant = std::variant<Obj>;
TEST(Test, Test) {
Obj obj;
Variant variant = obj;
}
When trying to compile this with clang++ there is this compile error:
error: no viable conversion from 'Obj' to 'Variant' (aka 'variant<Obj>')
Variant variant = obj;
^ ~~~
/usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/variant:1081:7: note: candidate constructor not viable: no known conversion from 'Obj' to 'const std::variant<Obj> &' for 1st argument
variant(const variant& __rhs) = default;
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/variant:1093:2: note: candidate template ignored: substitution failure [with _Tp = Obj &, $1 = void, $2 = void]: implicit instantiation of undefined template 'std::variant<Obj>::__to_type_impl<18446744073709551615, false>'
variant(_Tp&& __t)
^
(g++'s error only says
error: conversion from ‘Obj’ to non-scalar type ‘Variant’ {aka ‘std::variant<Obj>’} requested
Variant variant = obj;
^~~
)
When the line with MOCK_METHOD0 macro is commented out, the code compiles all right. I'm convinced it's the copy constructor (the one from line 1081) that gets invoked in that case.
Why is that? Will the problem disappear if I move to gmock 1.10? Or is it impossible to use variants of gmock mocks? Thanks for any explanation or a hint on how to find it myself.
If you expand the MOCK_METHOD0 macro, you will see that it inserts the following data member to your class definition:
class Obj
{
public:
// ...
mutable ::testing::FunctionMocker<void()> gmock0_mock_12;
};
Since you do not provide your own copy-constructor, one will be implicitly generated by the compiler. Its default implementation will try to perform a member-wise copy. However, checking the definition of FunctionMocker, one can see the following notice:
// There is no generally useful and implementable semantics of
// copying a mock object, so copying a mock is usually a user error.
// Thus we disallow copying function mockers. If the user really
// wants to copy a mock object, they should implement their own copy
// operation, for example:
//
// class MockFoo : public Foo {
// public:
// // Defines a copy constructor explicitly.
// MockFoo(const MockFoo& src) {}
// ...
// };
FunctionMocker(const FunctionMocker&) = delete;
FunctionMocker& operator=(const FunctionMocker&) = delete;
That is, FunctionMocker objects are non-copyable, and so are mock objects (their implicitly generated copy-constructors are also deleted).
That's reasonable. Should a copy of a mock have the same expectations? Should it double-check the expectations on destruction?
If you want to put the mock in a variant, you can build it in-place, either:
std::variant<Obj> variant(std::in_place_type_t<Obj>{});
or:
std::variant<Obj> variant;
variant.emplace<Obj>();
This is a similar question to others, BUT I have checked what this is being flagged as a duplicate as, and the general responses aren't helping me because I either do not understand them or they are irrelevant to my issue. I need help and/or a solution specifically to this problem. Please and thank you.
I am building a "programming language" (but it isn't really, just don't know how to describe it), and in my ContainerList class I keep getting this error saying that there is no matching call for function. Why am I getting this error?
I've tried manipulating where and when the constructor is used or defined or if it even exists. But there seems to be no luck. I looked into the MemoryContainer class and it doesn't seem like there is anything to cause the error.
Here is my code for the ContainerList class:
#include "MemoryContainer.cpp"
struct ContainerListItem{
int index = 0;
MemoryContainer item;
ContainerListItem* nextItem;
ContainerListItem(byte none) {}
};
class ContainerList{
public:
int getSize() {return size;}
void addContainer(MemoryContainer item){
ContainerListItem indexItem = ContainerListItem(1);
indexItem.item = item;
indexItem.index = size - 1;
indexItem.nextItem = &firstItem;
firstItem = indexItem;
size++;
}
MemoryContainer getContainer(int index){
ContainerListItem currentItem = ContainerListItem(1);
currentItem = firstItem;
while(currentItem.index != index)
currentItem = *currentItem.nextItem;
return currentItem.item;
}
private:
int size = 1;
ContainerListItem firstItem = ContainerListItem(1);
};
full error for the defined constructor:
In file included from Main.cpp:1:
ContainerList.cpp: In constructor ‘ContainerListItem::ContainerListItem(uint8_t)’:
ContainerList.cpp:7:34: error: no matching function for call to ‘MemoryContainer::MemoryContainer()’
ContainerListItem(byte none) {}
^
In file included from ContainerList.cpp:1,
from Main.cpp:1:
MemoryContainer.cpp:24:5: note: candidate: ‘MemoryContainer::MemoryContainer(uint64_t, std::__cxx11::string)’
MemoryContainer(lint ContainerSize, string name){
^~~~~~~~~~~~~~~
MemoryContainer.cpp:24:5: note: candidate expects 2 arguments, 0 provided
MemoryContainer.cpp:17:7: note: candidate: ‘MemoryContainer::MemoryContainer(const MemoryContainer&)’
class MemoryContainer{
^~~~~~~~~~~~~~~
MemoryContainer.cpp:17:7: note: candidate expects 1 argument, 0 provided
MemoryContainer.cpp:17:7: note: candidate: ‘MemoryContainer::MemoryContainer(MemoryContainer&&)’
MemoryContainer.cpp:17:7: note: candidate expects 1 argument, 0 provided
Your ContainerListItem class has a member that's another class:
MemoryContainer item;
However the constructor does not initialize it at all:
ContainerListItem(byte none) {}
The constructor is mostly empty.
All members of a class must be initialized by its constructor. If the constructor does not explicitly initialize a class member, it must have a default constructor that initializes it. A default constructor is a constructor that takes no parameters.
You did not show the declaration of your MemoryContainer class, but it must have a constructor that takes at least one parameter (actually there might be a few other reasons too, but this is the most likely one).
Which means that ContainerListItem must either explicitly initialize the class member, by constructing it, or you must add a default constructor to MemoryContainer.
This is exactly what your compiler is telling you, if you carefully read its error message:
error: no matching function for call to
‘MemoryContainer::MemoryContainer()’
The compiler is telling you that this class's default constructor does not exist. Because ContainerListItem does not explicitly initialize this class member, its default constructor must be called. But it's not declared.
You will find more information about the different ways of initializing class members in your C++ book. But if, for example, MemoryContainer's only constructor takes an int parameter, and you wish to initialize it, in this case, by calling its constructor with 0, your ContainerListItem constructor would read (using modern C++ uniform initialization syntax):
ContainerListItem(byte none) : item{0} {}
You need to figure out whether you want to implement a default constructor for MemoryContainer, or how to initialize it here. Nobody else can figure it out for you, this is a decision that only you can make.
I want to know if there's a way to make the = operator trigger the constructor (or any method) of a class upon its declaration
let's say
class foo
{
public:
string variable="";
foo(string var)
{
this->variable=var;
}
foo(){}
void operator=(string var)
{
this->variable=var;
}
}
int main()
{
foo obj="new foo object";
}
When I run that, it says "error: conversion from 'const char[15]' to non-scalar type 'foo' requested"
But when I do this
foo obj;
obj="new foo object";
It works
What can I do so the first method will work?
What can I do so the first method will work?
Provide a constructor that takes an argument of type char const *.
And use the initialization list of the constructors to initialize members, not assignments in the constructors body.
BTW:
foo obj = "new foo object";
does NOT call operator=().
Why don't you just use the constructor (that should be declared as explicit anyway, so the construct you want is actually bad practice IIRC)?
Just do:
foo obj("bar");
Also variable should not have a default empty value, the default constructor will create it properly.
You should also put variable in the initializer list.
When attempting to delete the default constructor and provide a new one with a default parameter (and therefore still be able to default construct the object), I receive an ambiguity error from g++.
class Thing
{
public:
Thing() = delete;
Thing(int arg = 0) : arg(arg) {}
private:
int arg;
};
int main(int, char**)
{
Thing thing;
return 0;
}
Compilation error below:
$ g++ deletedConstructorTest.C -std=c++11
deletedConstructorTest.C: In function "int main(int, char**)":
deletedConstructorTest.C:12:9: error: call of overloaded "Thing()" is ambiguous
Thing thing;
^
deletedConstructorTest.C:12:9: note: candidates are:
deletedConstructorTest.C:5:5: note: Thing::Thing(int)
Thing(int arg = 0) :arg(arg) {}
^
deletedConstructorTest.C:4:5: note: Thing::Thing() <deleted>
Thing() = delete;
^
If I modify the example above by removing the "Thing() = delete;" line then it compiles fine. I understand that the compiler won't generate a default constructor since I provided my own so that line is unnecessary but I was surprised at the compilation error.
Thanks in advance!
All declared overloads are considered during overload resolution, even if they are deleted or inaccessible. So you've declared two default constructors, both of which are an equally good match for default-initialisation, hence the ambiguity.
In this case, simply don't declare the zero-argument default constructor at all. The one-argument constructor is usable as a default constructor, and declaring any constructor inhibits the generation of an implicit default constructor.