error: no matching function for call to 'function namel' - c++

My final goal is to compute the power of a quadratic ideal which is implemented as struct variables in C using GMP library.
I have been given a library(ANTL), which contains generic optimized exponentiations using C++ templates, namespaces and NTL. This library does exponentiation for NTL types ZZ_p etc. and basic types like long, float etc..
I have to use the ANTL library to achieve my final goal - computing the power of an ideal, a C struct variable. Since I have never worked with templates and namespaces before I wanted to implement the power of a basic mpz_t variable before to see how everything works.
Now, I have four header files exp.hpp, expbin.hpp, impl.hpp, com.hpp and a main file exp.cpp as follows -
COM.HPP
#ifndef GMPL_COM_H
#define GMPL_COM_H
#include <gmp.h>
namespace GMPL {
template < class T >
inline void assign(T C, const T A)
{
mpz_set(C, A);
}
template<class T>
void mul (T C, const T A, const T B)
{
mpz_mul(C, A, B);
}
template<class T>
void sqr (T C, const T A)
{
mpz_mul(C, A, A);
}
}
#endif // guard
EXP.HPP
#ifndef EXP_H
#define EXP_H
#include "com.hpp"
namespace GMPL
{
template < class T >
class exp
{
public:
exp() {};
virtual ~exp() {};
virtual void power (T C, const T A, const NTL::ZZ & n) = 0;
};
} // GMPL
#endif // EXP_H
EXPBIN.HPP
#ifndef EXPBIN_H
#define EXPBIN_H
#include "exp.hpp"
namespace GMPL
{
template < class T >
class expbin : public exp<T>
{
public:
expbin() {};
~expbin() {};
void power (T C, const T A, const NTL::ZZ & n);
};
} // GMPL
// Unspecialized template definitions.
#include "impl.hpp"
#endif // EXPBIN_H
IMPL.HPP
using namespace GMPL;
//
// compute A^n using standard left-to-right binary method
//
template < class T >
void expbin<T>::power (T C, const T A, const NTL::ZZ & n)
{
assign(C,A);
for (register long i = NumBits(n)-2 ; i >= 0 ; i--)
{
sqr(C, C);
if (bit(n, i) == 1)
mul(C, C, A);
}
}
EXP.CPP
#include <NTL/lzz_p.h>
#include <gmp.h>
namespace GMPL {}
using namespace GMPL;
#include "expbin.hpp"
NTL_CLIENT
int main ()
{
// NTL variables
ZZ n;
// GMP variables
mpz_t aa;
mpz_t bb;
mpz_init(aa);
mpz_init(bb);
// generate random exponent of size 512 bits
RandomLen (n, 512); // NTL function
// initialize exponentiation classes
expbin<mpz_t> obj;
// compute a^n with available methods
obj.power (bb,aa,n);
// check and output results
gmp_printf("%Zd", bb);
}
when I try to compile EXP.CPP using (as mentioned on Victor Shoup's NTL documentation online)
g++ -g -O2 -std=c++11 -pthread -march=native exp.cpp -o t -lntl -lgmp -lm
I get the following error messages-
$ g++ -g -O2 -std=c++11 -pthread -march=native exp.cpp -o t -lntl -lgmp -lm
In file included from exp.cpp:8:
In file included from ./expbin.hpp:46:
./impl.hpp:16:10: warning: 'register' storage class specifier is deprecated and
incompatible with C++1z [-Wdeprecated-register]
for (register long i = NumBits(n)-2 ; i >= 0 ; i--)
^~~~~~~~~
./impl.hpp:15:5: error: no matching function for call to 'assign'
assign(C,A);
^~~~~~
exp.cpp:28:9: note: in instantiation of member function
'GMPL::expbin<__mpz_struct [1]>::power' requested here
obj.power (bb,aa,n);
^
./com.hpp:16:17: note: candidate template ignored: deduced conflicting types for
parameter 'T' ('__mpz_struct *' vs. 'const __mpz_struct *')
inline void assign(T C, const T A)
^
In file included from exp.cpp:8:
In file included from ./expbin.hpp:46:
./impl.hpp:20:13: error: no matching function for call to 'mul'
mul(C, C, A);
^~~
./com.hpp:22:10: note: candidate template ignored: deduced conflicting types for
parameter 'T' ('__mpz_struct *' vs. 'const __mpz_struct *')
void mul (T C, const T A, const T B)
Assiduous googling about these errors shows that one has to have an empty constructor in the parent class but I already have it.
I know the compile statement is correct because other than that nothing else works when using NTL. At this point I ran out of ideas to fix this. Thanks in advance.
EDIT
This question has been resolved. I wish for this question to be closed or removed.

One solution would be to not use templates for your function wrappers. It seems like there would be only one template parameter that ever makes sense (i.e. T replaced by mpz_t), given that the template parameter has to be compatible with mpz_set. Templates seem like the wrong tool for the job. Just define your wrappers taking parameters of type mpz_t and const mpz_t:
inline void assign(mpz_t C, const mpz_t A)
{
mpz_set(C, A);
}
You did say you wanted to learn templates, but using them in an inappropriate context is not going to be that helpful. And you still have the templates for your classes to learn from.
That being said, I can interpret the compiler messages for you.
warning: 'register' storage class specifier is deprecated and
incompatible with C++1z [-Wdeprecated-register]
for (register long i = NumBits(n)-2 ; i >= 0 ; i--)
This is an easy one to fix. Get rid of "register" in that line. It is no longer a performance optimization.
error: no matching function for call to 'assign'
assign(C,A);
[...]
note: candidate template ignored: deduced conflicting types for
parameter 'T'
The compiler is having trouble figuring out what to use as the template parameter in this function call. There are two function arguments, each implying what the template parameter for assign should be. (This is distinct from the template parameter for expbin, even though both are named T.) It's a problem when the implications are in conflict. One way to make this work should be to specify what you want the parameter to be, as in
assign<T>(C, A);
This makes it explicit that the template parameter for assign (given between < and >) is supposed to be the template parameter for expbin (the meaning of T in this context).
Note: The templates you defined look like they might normally work without having to specify T like this. However, mpz_t is technically an array of one structure (not simply a structure), and arrays used as arguments can decay, which can lead to type confusion.
error: no matching function for call to 'mul'
mul(C, C, A);
note: candidate template ignored: deduced conflicting types for
parameter 'T'
Same (although in this case there are three function arguments, so three deduced candidates for T).
mul<T>(C, C, A);

Related

Assignment operator overloading with a C++ class template

I have a C++ class template for representing real- and complex valued 2D fields. I'd like to overload the assignment operator to achieve deep-copying the data from one field to another. For now, I've restricted the data to either double or std::complex<double>. This means there are 4 different cases to consider: double-to-double, double-to-std::complex<double>, std::complex<double>-to-double and std::complex<double>-to-std::complex<double>. I want to handle the std::complex<double>-to-double case by taking the real part of the complex value; for the other cases it's just a trivial assignment. I'm however struggling to get the code to compile. The following is a simple mock version that captures the issues:
#include <complex>
template<class T>
class Number {
private:
// should make Number<T>.m_value visible to Number<U>
template<class U>
friend class Number;
T m_value;
public:
Number(const T value) : m_value{value} {
// restricting the data
static_assert(
std::is_same<T, double>::value || std::is_same<T, std::complex<double>>::value,
"Error: Number::Number: Only 'double' and 'std::complex<double>' are supported currently!"
);
// no copying allowed
Number(const Number& orig) = delete;
};
// general case
template<class U>
Number<T>& operator=(const Number<U>& another) {
m_value = another.m_value;
return *this;
}
};
// specialization
template<> Number<double>& Number<double>::operator=(const Number<std::complex<double>>& another) {
m_value = std::real(another.m_value);
}
int main(int argc, char** argv) {
const std::complex<double> I{0.0, 1.0};
Number<double> n{0.0};
Number<std::complex<double>> m{1.0 + I*2.0};
n = m;
return 0;
}
Compiler output:
g++ -c -g -std=c++14 -MMD -MP -MF "build/Debug/GNU-Linux/main.o.d" -o build/Debug/GNU-Linux/main.o main.cpp
main.cpp:28:28: error: template-id ‘operator=<>’ for ‘Number<double>& Number<double>::operator=(const Number<std::complex<double> >&)’ does not match any template declaration
template<> Number<double>& Number<double>::operator=(const Number<std::complex<double>>& another) {
^
main.cpp:28:97: note: saw 1 ‘template<>’, need 2 for specializing a member function template
template<> Number<double>& Number<double>::operator=(const Number<std::complex<double>>& another) {
^
main.cpp: In instantiation of ‘Number<T>& Number<T>::operator=(const Number<U>&) [with U = std::complex<double>; T = double]’:
main.cpp:36:5: required from here
main.cpp:23:15: error: cannot convert ‘const std::complex<double>’ to ‘double’ in assignment
m_value = another.m_value;
^
I can't seem to figure out how to implement the assignment overloads. I have tried to find a solution for my problem (e.g. from "Similar questions") and have come across many helpful questions and answers, and have incorporated many things from them to my code. I however haven't found a solution to my specific problem and seem to be stuck. Any suggestions? Thanks!
It actually says what it expects in the line:
main.cpp:28:97: note: saw 1 ‘template<>’, need 2 for specializing a member function template
You need one 'template<>' to specialize T in class template and one more to specialize U in member function template:
template<>
template<>
Number<double>& Number<double>::operator=(const Number<std::complex<double>>& another) { ... }

class template fails to compile when named lambda is used as template class argument or constructor argument

I'm currently experimenting with class template programming and I came across this weird behavior that I cant understand when passing a named lambda as its argument. Could somebody explain why (1) & (2) below does not work?
template<typename Predicate>
class Test{
public:
Test(Predicate p) : _pred(p) {}
private:
Predicate _pred;
};
int main(){
auto isEven = [](const auto& x){ return x%2 == 0; };
// Working cases
Test([](const auto& x){ return x%2 == 0; });
Test{isEven};
auto testObject = Test(isEven);
// Compilation Error cases
Test(isEven); // (1) Why??? Most vexing parse? not assigned to a variable? I cant understand why this fails to compile.
Test<decltype(isEven)>(isEven); // (2) Basically same as (1) but with a workaround. I'm using c++17 features, so I expect automatic class parameter type deduction via its arguments
return 0;
};
Compiler Error message: Same for (1) & (2)
cpp/test_zone/main.cpp: In function ‘int main()’:
cpp/test_zone/main.cpp:672:16: error: class template argument deduction failed:
Test(isEven);
^
cpp/test_zone/main.cpp:672:16: error: no matching function for call to ‘Test()’
cpp/test_zone/main.cpp:623:5: note: candidate: template<class Predicate> Test(Predicate)-> Test<Predicate>
Test(Predicate p): _p(p){
^~~~
cpp/test_zone/main.cpp:623:5: note: template argument deduction/substitution failed:
cpp/test_zone/main.cpp:672:16: note: candidate expects 1 argument, 0 provided
Test(isEven);
^
Please forgive my formatting, and compile error message snippet as it does not match exact lines. I'm using g++ 7.4.0, and compiling with c++17 features.
In C++, you can declare a variable as
int(i);
which is the same as
int i;
In your case, the lines
Test(isEven);
Test<decltype(isEven)>(isEven);
are compiled as though you are declaring the variable isEven. I am surprised that the error message from your compiler is so different than what I hoped to see.
You can reproduce the problem with a simple class too.
class Test{
public:
Test(int i) : _i(i) {}
private:
int _i;
};
int main(){
int i = 10;
Test(i);
return 0;
};
Error from my compiler, g++ 7.4.0:
$ g++ -std=c++17 -Wall socc.cc -o socc
socc.cc: In function ‘int main()’:
socc.cc:15:11: error: conflicting declaration ‘Test i’
Test(i);
^
socc.cc:10:9: note: previous declaration as ‘int i’
int i = 10;
As you said, this is a most vexing parse issue; Test(isEven); is trying to redefine a variable with name isEven, and same for Test<decltype(isEven)>(isEven);.
As you showed, you can use {} instead of (), this is the best solution since C++11; or you can add additional parentheses (to make it a function-style cast).
(Test(isEven));
(Test<decltype(isEven)>(isEven));
LIVE

What am i doing wrong in this code in C++ , Generic Functions?

I was trying out a sample generic function in C++ , the code follows:
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
template <typename T>
T max(T a, T b){
return (a>b)?a:b;
}
int main()
{
int a=2,b=4;
float af = 2.01,bf=2.012;
double ad = 2.11,bd=1.22;
cout<<max(a,b);
}
I am getting the error as
main.cpp: In function ‘int main()’:
main.cpp:20:18: error: call of overloaded ‘max(int&, int&)’ is ambiguous
cout<<max(a,b);
^
main.cpp:20:18: note: candidates are:
main.cpp:9:3: note: T max(T, T) [with T = int]
T max(T a, T b){
^main.cpp: In function ‘int main()’:
main.cpp:20:18: error: call of overloaded ‘max(int&, int&)’ is ambiguous
cout<<max(a,b);
^
main.cpp:20:18: note: candidates are:
main.cpp:9:3: note: T max(T, T) [with T = int]
T max(T a, T b){
^main.cpp: In function ‘int main()’:
main.cpp:20:18: error: call of overloaded ‘max(int&, int&)’ is ambiguous
cout<<max(a,b);
^
main.cpp:20:18: note: candidates are:
main.cpp:9:3: note: T max(T, T) [with T = int]
T max(T a, T b){
^
What am I doing wrong here ?
What is meant by call of overloaded max(int&, int&) is ambiguous ?
Why am I getting its argument shown as & where as there was no such syntax defined by me above ?
The problem is that C++ already has a std::max definition.
Pick another name and everything should be fine.
In C++ the using namespace std approach is a bad idea as thousands of names will be injected. Just get the habit of typing std:: in front of standard names.
Remember also that saving time when writing is not really that important, what is important is saving time when reading (normally code is written just once but read and understood many times).
std:: in front of standard names actually speeds up reading and lets understanding on the spot that what is being used is part of the standard library (not everyone knows the whole standard library by heart).
Skypjack and 6502's answers are spot on so I won't go over that here.
It is also worth noting that the standard's version of max is not that clever. You can cause it not to compile with code like this:
int main()
{
int a = 0;
double b = 1;
auto c = std::max(a, b);
}
yields error message:
16 : error: no matching function for call to 'max(int&, double&)'
If we wanted to rewrite max, we might imagine that we were improving it by writing it this way:
#include <type_traits>
namespace notstd {
template <typename T1, class T2>
auto max_any(T1 a, T2 b) -> std::common_type_t<T1, T2>
{
return (a>b) ? a : b;
}
}
int main()
{
int a = 0;
double b = 1;
auto c = notstd::max_any(a, b);
}
But of course there would be some consequences.
Firstly, max_any is now forced to take copies and (possibly) perform conversions. For integers and doubles this is almost not worth mentioning.
But if T1 and T2 were two classes of object that had appropriate conversion operators, calling max_any on them could potentially be an expensive operation. It might also have material side-effects.
For this reason, std::max is defined in terms of arguments of type T&. It forces the caller to perform the conversion. It turns out that this is not a limitation of std::max. It is a safety feature.
The function does not inject any hidden side-effects into your code.
In order to maintain 'the path of least surprise' in its behaviour, the standard library sometimes requires that its users spell out the surprising behaviour that they want.
Example of surprising behaviour
This program will compile perfectly:
#include <cstdlib>
#include <iostream>
namespace notstd {
template <typename T1, class T2>
auto max_any(T1 a, T2 b)
{
return (b < a) ? a : b;
}
}
struct A {
A() = default;
};
struct B {
B() = default;
B (A const&) { std::exit(100); }
};
bool operator<(B const&, A const &) { return true; }
int main()
{
A a;
B b;
auto c = notstd::max_any(a, b);
std::cout << "Hello, World\n";
}
But it will never print "Hello, World".
Someone maintaining this code might be surprised to learn that.
There exists already a max function in the standard template library (namely std::max).
Using the using namespace directive, you are importing the names from the std:: namespace to the one in which you are using the declaration itself.
You can still use the following line to pick your implementation of max:
cout << ::max(a,b);
Otherwise, as someone already mentioned, you can choose a different name for your function or use directly the one fron the standard template library.

Do templates provide type checking

So I understand that templates can provide a way to do generic programming for example :
template <typename T>
T add(T x, T y){ return x + y}
Now I am wondering is there any type check templates provide? Or should I just define x and y as an integer to avoid errors.
If you define operator+ for the type T, then there would be no problem.
Definitely, there will be type checking, so you won't be able to do something like:
string c = add(3UL, 2.0E4); /* ERROR: the type of the result and the types of the arguments must match */
Also, as has been appointed, T must be a type with add operator + defined on it. As far as you obey these rules, you are free to do whatever you want with your generic function.
#include <iostream>
using namespace std;
template <typename T>
T add(T a, T b)
{
return a + b;
}
int main()
{
string c = add(3UL, 'A');
}
Will lead to:
$ make pru
g++ pru.cc -o pru
pru.cc: In function ‘int main()’:
pru.cc:13:28: error: no matching function for call to ‘add(long unsigned int, char)’
pru.cc:13:28: note: candidate is:
pru.cc:6:3: note: template<class T> T add(T, T)
make: *** [pru] Error 1

Why take '<' as 'operator<' rather than a mark to enclose the template argument? [duplicate]

This question already has answers here:
Where and why do I have to put the "template" and "typename" keywords?
(8 answers)
Closed 8 years ago.
My C++ code is below:
//test.cpp
#include <iostream>
using namespace std;
template <int SIZE, class T>
struct A
{
void g(int x, const T& t)
{
t.f<SIZE>(x);
}
};
struct B
{
template <int SIZE>
void f(int x) const
{
cout << SIZE << ": " << x << endl;
}
};
int main(void)
{
A<3, B> a;
B b;
a.g(9, b);
return 0;
}
I got a surprising error when compiled it with g++(version is 4.8.2):
test.cpp: In instantiation of ‘void A<SIZE, T>::g(int, const T&) [with int SIZE = 3; T = B]’:
test.cpp:27:13: required from here
test.cpp:9:12: error: invalid operands of types ‘<unresolved overloaded function type>’ and ‘int’ to binary ‘operator<’
t.f<SIZE>(x);
^
Why it take < as operator< rather than a mark to enclose the template argument?
Because the code is inherently ambiguous1 so the compiler has to decide either way. And it was arbitrarily decided by the C++ standards committee that if in doubt, assume that a name is a variable, not a type.
If you want your code to be parsed as a template, you need to say so explicitly:
t.template f<SIZE>(x);
1 At the time where this code is parsed, the type of t is not yet known since it’s a template. Consider the following type:
struct T {
int f;
};
If you now instantiate A with that type, you get (pseudocode since the template is instantiated):
void A<3, T>::g(int x, T const& t) {
((t.f) < 3) > x;
}
I’ve added parentheses for clarification: this is how the compiler sees your code, and it’s entirely valid (although nonsensical).
Let's look at:
t.f < SIZE > (x);
Whitespace is not significant. If t.fis a variable this could be saying: Do t.f < SIZE and then do (that result) > x.
Further, the compiler doesn't know yet whether t.f is a variable or a function template. Remember that templates can be specialized, so even if it seems that t.f is a function template now; later on in the piece this code could be instantiated from a specialization of B where t.f is a variable.
To resolve this dilemma, names which are ambiguous are treated as variable names unless you specifically indicate that they are something else. In this case that's done by writing t.template f ; a similar principle has us write typename T::iterator when T is a dependent name.