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.
Related
I'm trying to use decltype, but I got the same error every time when I was trying compile.
#include <iostream>
#include <cmath>
using namespace std;
class Polygon {
private:
double bok;
int katy;
public:
Polygon(int katy,double bok): katy (katy),bok (bok) {};
void scale(double s){ bok*=s;};
double area () const{
return (katy*(bok*bok))/(4.0*tan((M_PI/katy)));}};
int main(){
Polygon polygon(7,10.);
polygon.scale(2.);
cout<<polygon.area()<<endl;
if(!std::is_same<decltype(scale),void (Polygon*,double)>::value){
cout<<'p';
}
}
I got a error: "
error: ‘scale’ was not declared in this scope; did you mean ‘scalb’?
28 | if(!std::is_same<decltype(scale),void (Polygon*,double)>::value){
"
What's wrong?
You need to take a pointer to the member function and prefix it with the class scope in order to refer to it:
if (!std::is_same<decltype(&Polygon::scale), void(Polygon*, double)>::value) {
cout<<'p';
}
Be advised, however, that member function type is not a plain function pointer, as for each class there is special type defined within the class scope, which follows this pattern: ReturnType(ClassName::*)(args). Thus in your scenario, if you expect std::is_same to match the function, you should specify the conditional expression as follows:
std::is_same_v<
decltype(&Polygon::scale),
void(Polygon::*)(double)
>
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.
i'm trying to implement a clone of the json serialization library nlohmann::json as a learning experience, and i'm having trouble with the interface for user defined (json<->User type) conversion.
Basically i want the user to be able to overload two function: to_json(json&, const Type&) and from_json(const json&, Type&). Then the library will use overload resolution to call theses function in the templated operator= and one argument constructor.
It works fine when i'm just defining theses function directly but when i try to make a template definition for multiple types (in this example the class S) the linker can't find the definition.
I've tried to explicitly instantiate the function for individual instances of the templated class although i would prefer avoiding having to do that in the final product.
I'm guessing it has to do with the fact that templated function don't have the same signature than free function, but i don't see what i can do to make it work. What am i missing ? I also couldn't find result on google so is it a documented pattern or an anti pattern ?
Thanks you. Below i tried to minimize my problem in one short example.
Class.hpp
#pragma once
#include <cstdio>
template<size_t i>
class S {
size_t n = i;
};
template<size_t i>
void g(const S<i>& s) {
printf("S<%u>\n", i);
}
Class.cpp
#include "Class.hpp"
template void g<10>(const S<10>&); // <-- Even with explicitly instanciation
void g(const bool& b) {
printf("%s\n", b ? "true" : "false");
}
main.cpp
#include "Class.hpp"
template<typename T>
void f(T t) {
extern void g(const T&);
g(t);
}
int main(int, char**) {
S<10> s;
//f(s); <-- linker error: void g(class S<10> const &) not found.
f(false);
}
The name lookup for g in g(t) call stops as soon as it finds extern void g(const T&); declaration; it never sees the declaration of the function template. So the compiler generates a call to a regular non-template function named g taking const S<10>&. But no such function is defined in your program - hence linker error.
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.
I want to iterate over a QMultiMap using
QMultiMap<double, TSortable>::const_iterator it;`
but the compiler complains
error: expected ‘;’ before ‘it’
resulting in a
error: ‘it’ was not declared in this scope
for every usage. I tried ConstIterator, const_iterator and even the slower Iterator without any success. Is it even possible to use Q(Multi)Map with a template class? Why can't I declare an Iterator when definition (as void*) is ok?
I use the following code (include guard omitted):
#include <QtCore/QDebug>
#include <QtCore/QMap>
#include <QtCore/QMultiMap>
#include <limits>
/** TSortable has to implement minDistance() and maxDistance() */
template<class TSortable>
class PriorityQueue {
public:
PriorityQueue(int limitTopCount)
: limitTopCount_(limitTopCount), actMaxLimit_(std::numeric_limits<double>::max())
{
}
virtual ~PriorityQueue(){}
private:
void updateActMaxLimit(){
if(maxMap_.count() < limitTopCount_){
// if there are not enogh members, there is no upper limit for insert
actMaxLimit_ = std::numeric_limits<double>::max();
return;
}
// determine new max limit
QMultiMap<double, TSortable>::const_iterator it;
it = maxMap_.constBegin();
int act = 0;
while(act!=limitTopCount_){
++it;// forward to kMax
}
actMaxLimit_ = it.key();
}
const int limitTopCount_;
double actMaxLimit_;
QMultiMap<double, TSortable> maxMap_;// key=maxDistance
};
GCC gives this error before the one you quoted:
error: need ‘typename’ before ‘QMultiMap<double, TSortable>::const_iterator’ because ‘QMultiMap<double, TSortable>’ is a dependent scope
which explains the problem. Add the typename keyword:
typename QMultiMap<double, TSortable>::const_iterator it;
and it will build.