ambiguity of overloaded function taking constant Eigen argument - c++

I've designed a class with two overloaded functions taking Eigen data structures of different sizes.
The code compiles as long as I'm passing lvalues but if I pass an rvalue I get a compiler error ambiguity because both return the same ConstantReturnType.
Here is a MWE:
#include <iostream>
#include <Eigen/Geometry>
using namespace std;
using namespace Eigen;
class MyOverloadAmbiguity {
public:
void ambiguousOverload(const Eigen::Vector3d& v) {
std::cout << "I'm taking a Vector3d\n";
}
void ambiguousOverload(const Eigen::Vector4d& v){
std::cout << "I'm taking a Vector4d\n";
}
};
int main()
{
MyOverloadAmbiguity moa;
Eigen::Vector3d v3;
moa.ambiguousOverload(v3); // <--- this works
moa.ambiguousOverload(Eigen::Vector4d::Zero()); // <--- this doesn't
return 0;
}
main.cpp:26: error: call of overloaded ‘ambiguousOverload(const ConstantReturnType)’ is ambiguous
26 | moa.ambiguousOverload(Eigen::Vector4d::Zero());
| ^
main.cpp:10:8: note: candidate: ‘void MyOverloadAmbiguity::ambiguousOverload(const Vector3d&)’
10 | void ambiguousOverload(const Eigen::Vector3d& v) {
| ^~~~~~~~~~~~~~~~~
main.cpp:13:8: note: candidate: ‘void MyOverloadAmbiguity::ambiguousOverload(const Vector4d&)’
13 | void ambiguousOverload(const Eigen::Vector4d& v){
| ^~~~~~~~~~~~~~~~~
Is there a way to avoid this without explicitly changing the function names or add extra arguments just to avoid the ambiguity?

Your example does not work because the return type of Zero() is not a matrix, but an Eigen expression.
Thus, one way of achieving what you want with minimal changes is to use explicit matrix evaluation:
moa.ambiguousOverload(Eigen::Vector4d::Zero().eval());
You may also want to consider writing functions taking Eigen expressions as parameters (rather than explicit matrices), as an alternative solution.

Related

cpp no matching function call for call to constructor. Why?

Below is my code:
// this code illustrates iterating through a nested hashmap.
#include <iostream>
#include "imported.hpp"
#include <string>
#include <iomanip>
#include <vector>
using namespace std;
#define MAX_LINE_LENGTH 999
using namespace std;
class State
{
public:
vector<string> vec;
string state_string;
State(string state_string, vector<string> vec);
};
State::State(string state_string, vector<string> vec)
{
this->state_string = state_string;
this->vec = vec;
}
class Heuristic
{
public:
State goal_state;
string type;
Heuristic(string type, State goal_state);
};
Heuristic::Heuristic(string type, State goal_state)
{
this->type = type;
this->goal_state = goal_state;
}
int main(int argc, char const *argv[])
{
}
When I try to compile it using:
g++ filename.cpp
The following output is produced:
$ g++ main.cpp
main.cpp: In constructor ‘Heuristic::Heuristic(std::string, State)’:
main.cpp:36:51: error: no matching function for call to ‘State::State()’
Heuristic::Heuristic(string type, State goal_state)
^
main.cpp:21:1: note: candidate: State::State(std::string, std::vector<std::basic_string<char> >)
State::State(string state_string, vector<string> vec)
^~~~~
main.cpp:21:1: note: candidate expects 2 arguments, 0 provided
main.cpp:12:7: note: candidate: State::State(const State&)
class State
^~~~~
main.cpp:12:7: note: candidate expects 1 argument, 0 provided
main.cpp:12:7: note: candidate: State::State(State&&)
main.cpp:12:7: note: candidate expects 1 argument, 0 provided
I am confused as to why this is happening since I am not even calling the constructor but rather am defining a function's method signature into which the user should be able to pass an existent State object. Please assist.
The Heuristic constructor is built using assignment operators which involves the default construction of its member objects. Since State does not have a default constructor, this form of construction will fail.
There are two ways of solving this:
If the members have user-defined constructors, provide default-constructors also for them .
Use initializer lists for your constructor instead of assignments within the body of the constructor.
Of these two methods, the second one is more preferable. The reasons for this are outlined in the FAQ: Should my constructors use “initialization lists” or “assignment”?

Call of overloaded function is ambiguous although different namespace

I do understand why the following would be a problem if no namespaces were used. The call would be ambiguous indeed. I thought "using stD::swap;" would define which method to use.
Why does it work for "int" but not a "class"?
#include <memory>
namespace TEST {
class Dummy{};
void swap(Dummy a){};
void sw(int x){};
}
namespace stD {
void swap(TEST::Dummy a){};
void sw(int x){};
class aClass{
public:
void F()
{
using stD::swap;
TEST::Dummy x;
swap(x);
}
void I()
{
using stD::sw;
int b = 0;
sw(b);
}
};
}
This is the error message:
../src/Test.h: In member function ‘void stD::aClass::F()’:
../src/Test.h:26:9: error: call of overloaded ‘swap(TEST::Dummy&)’ is ambiguous
swap(x);
^
../src/Test.h:26:9: note: candidates are:
../src/Test.h:17:6: note: void stD::swap(TEST::Dummy)
void swap(TEST::Dummy a){};
^
../src/Test.h:10:6: note: void TEST::swap(TEST::Dummy)
void swap(Dummy a){};
^
I thank you very much in advance for an answer.
This line is using argument dependent lookup
TEST::Dummy x;
swap(x);
So it will find both void stD::swap(TEST::Dummy) as well as void TEST::swap(TEST::Dummy) because x carries the TEST:: namespace.
In the latter case int b = 0; the variable b is not in a namespace, so the only valid function to call would be stD::sw due to your using statement.

no known conversion for templated vs const non-templated vector

In my actual code, I included a library, and as soon as I did that, it started crashing. I managed to sort of extract some of that code into this minimal example, that demonstrates the same kind of error:
// g++ -std=c++11 -g -o test-classcall.exe test-classcall.cpp
#include <iostream>
#include <vector>
#include <stdio.h>
class Cat
{
public:
int Age;
Cat() : Age(0) {}
};
std::vector<Cat> myPCats;
typedef std::vector<Cat> TDVectCats;
TDVectCats myTDCats;
void loopSomeCats() {
printf("this function just to cause searching for matching calls\n");
}
void loopSomeCats(TDVectCats& incats) {
std::vector<Cat>::iterator iter;
for(iter = incats.begin(); iter != incats.end(); iter++) {
printf("hm\n");
}
}
const std::vector<Cat> & getSomeCats() {
return myPCats;
}
void doSomething() {
loopSomeCats(getSomeCats());
}
int main() {
myTDCats.push_back(Cat());
myTDCats.push_back(Cat());
myPCats.push_back(Cat());
doSomething();
std::cout << "Hello World! " << std::endl;
return 0;
}
The result is:
$ g++ -std=c++11 -g -o test-classcall.exe test-classcall.cpp
test-classcall.cpp: In function ‘void doSomething()’:
test-classcall.cpp:36:29: error: no matching function for call to ‘loopSomeCats(const std::vector<Cat>&)’
loopSomeCats(getSomeCats());
^
test-classcall.cpp:36:29: note: candidates are:
test-classcall.cpp:20:6: note: void loopSomeCats()
void loopSomeCats() {
^
test-classcall.cpp:20:6: note: candidate expects 0 arguments, 1 provided
test-classcall.cpp:24:6: note: void loopSomeCats(TDVectCats&)
void loopSomeCats(TDVectCats& incats) {
^
test-classcall.cpp:24:6: note: no known conversion for argument 1 from ‘const std::vector<Cat>’ to ‘TDVectCats& {aka std::vector<Cat>&}’
What especially confuses me, is the last "no known conversion for argument 1 from ‘const std::vector<Cat>’ to ‘TDVectCats& {aka std::vector<Cat>&}’", as if it cannot convert a vector of something, into the vector of the same something, just because of typedef? Or it maybe has to do with the const - but I simply cannot see what I need to change, in order to have a call like loopSomeCats(getSomeCats()); succeed...
You can't pass a reference to a const object to a non-const reference.
loopSomeCats takes a std::vector<Cat>& as argument, and you want to pass a const std::vector<Cat>& to it, but that's not possible.
The const would mean that you don't want anyone to modify the return value, but if you pass it to a function which just takes a non-const reference, then theoretically the function can modify the reference, and you don't want that.
You should drop the const if you want the return value to be modified.

Resolving conflicts in methods calling functions with the same name in C++

Consider the following stripped-down example of a (templated) C++ structure for square matrices (it doesn't need to be templated for the problem to occur):
#include <array>
#include <complex>
using namespace std;
double conj (double &x) { return x; };
template <typename T, int N>
struct matrix: array<T,N*N> {
void conj() {
for (int ij=0; ij<100; ++ij) {
T z = (*this)[ij];
(*this)[ij] = conj(z);
}
}
};
int main() {
matrix<double,10> a;
a.conj();
return 0;
}
I want to implement a method that performs matrix complex conjugation, using the name .conj() to coincide with the naming system used in the < complex > library. However, I get the following error:
$ g++ example.cpp -std=c++11
example.cpp: In instantiation of ‘void matrix<T, N>::conj() [with T = double; int N = 10]’:
example.cpp:19:12: required from here
example.cpp:12:26: error: no matching function for call to ‘matrix<double, 10>::conj(double&)’
(*this)[ij] = conj(z);
^
example.cpp:12:26: note: candidate is:
example.cpp:9:10: note: void matrix<T, N>::conj() [with T = double; int N = 10]
void conj() {
^
example.cpp:9:10: note: candidate expects 0 arguments, 1 provided
The compiler doesn't seem to recognize the function conj(double&) called inside the method of the same name, and defined before the structure. Instead, it tries to call the method conj().
Why isn't the compiler able to resolve this naming conflict, and what would be the solution that preserves the naming? Of course, if I change the name of the method to something different to conj, the code compiles and runs normally.
The member function hides functions of the same name in a wider scope.
Use the qualified name ::conj to refer to the function in the global namespace.

How to take a 2D view of Boost.MultiArray as an argument into function?

I have a 3D array of doubles. I want to write simple & generic function to print 2D slices of it.
Code:
#include <cstdio>
#include <boost/multi_array.hpp>
template<class M> // any model of MultiArray concept
void printFloatMatrix(typename M::template array_view<2u>::type matrix) {
using std::printf;
for(auto& row : matrix) {
for(auto& elem : row) {
printf("%5.3f ", elem);
}
printf("\n");
}
}
int main() {
typedef boost::multi_array<double,3> data_t;
data_t test_matrix{data_t::extent_gen()[10][10][2]};
// ...
using boost::indices;
using boost::multi_array_types::index_range;
printFloatMatrix(test_matrix[ indices[index_range()] [index_range()] [0] ]);
}
With GCC this produces the error message:
test.cpp: In function ‘int main()’:
test.cpp:24:79: error: no matching function for call to ‘printFloatMatrix(boost::multi_array_ref<double, 3u>::array_view<2u>::type)’
test.cpp:24:79: note: candidate is:
test.cpp:5:6: note: template<class M> void printFloatMatrix(typename M::array_view<2u>::type)
Why the error?
Why doesn't M is inferred to be boost::multi_array_ref<double, 3u>?
How do I write the prototype that'd work?
I'm not able to spell the exact reason why C++ type inference fails here, but changing the function prototype to template<class M> void printFloatMatrix(const M& matrix) worked.
The prototype is uselessly wide now, though. With high chance it will bite me in the future. This situation will hopefully be fixed with the advent of concepts, or can alternatively be worked-around with static asserts.
Thanks to ##c++ at Freenode.