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

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.

Related

error: no matching function for call to 'function namel'

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);

Constraints not satisfied for template template concept requiring static template method

I'm trying to implement Functor and various other category-theoretic concepts using C++ concepts, but am getting compile errors:
http://coliru.stacked-crooked.com/a/e8b6eb387229bddf
Here's my full code (I know that requiring fmap<int, int> does not verify fmap for any two types, and I plan to change it to fmap<int, std::string> or something to achieve a slightly stronger test -- or instead, possibly alter the Functor concept so that it takes in addition to F, two types T and U and verifies the existence of fmap<T, U>, but that's all after I figure out how to fix the error that I'm getting):
#include <functional>
#include <iostream>
#include <vector>
// empty Functor_Impl struct - specialize for each functor
template<template<class> class F> struct Functor_Impl {};
// std::vector Functor implementation
template<>
struct Functor_Impl<std::vector> {
template<class T, class U>
static std::vector<U> fmap(std::vector<T> x, std::function<U(T)> f) {
std::vector<U> out;
out.reserve(x.size());
for (int i = 0; i < x.size(); i++) {
out.push_back(f(x[i]));
}
return out;
}
};
// Functor concept requires Functor_Impl<F> to have fmap
template<template<class> class F>
concept bool Functor = requires(F<int> x) {
{Functor_Impl<F>::template fmap<int, int>(x)} -> F<int>;
};
// Test function using constraint.
template<template<class> class F, class T>
requires Functor<F>
F<T> mult_by_2(F<T> a) {
return Functor_Impl<F>::template fmap<T, T>(a, [](T x) {
return x * 2;
});
}
int main() {
std::vector<int> x = {1, 2, 3};
std::vector<int> x2 = mult_by_2(x);
for (int i = 0; i < x2.size(); i++) {
std::cout << x2[i] << std::endl;
}
}
And the compile error:
lol#foldingmachinebox:~/p/website-editor$ g++ foo.cpp -std=c++17 -fconcepts -o foo
foo.cpp: In function ‘int main()’:
foo.cpp:39:38: error: cannot call function ‘F<T> mult_by_2(F<T>) [with F = std::vector; T = int]’
std::vector<int> x2 = mult_by_2(x);
^
foo.cpp:31:6: note: constraints not satisfied
F<T> mult_by_2(F<T> a) {
^~~~~~~~~
foo.cpp:24:14: note: within ‘template<template<class> class F> concept const bool Functor<F> [with F = std::vector]’
concept bool Functor = requires(F<int> x) {
^~~~~~~
foo.cpp:24:14: note: with ‘std::vector<int> x’
foo.cpp:24:14: note: the required expression ‘Functor_Impl<F>::fmap<int, int>(x)’ would be ill-formed
I'm guessing that my syntax for the concept itself is wrong - that it's treating a variable as a function, or vice versa, since I'm not very familiar with the concept syntax, and in addition some of the example code on cppreference.com does not compile under GCC's implementation (e.g. concept EqualityComparable does not compile, it must be changed to concept bool EqualityComparable).
If I remove requires Functor<F> from the mult_by_2 function declaration, then the code compiles and runs.
The problem is exactly what the error message says: Functor_Impl<F>::template fmap<int, int>(x) is not a valid expression. Functor_Impl<std::vector>::fmap has two parameters, not one.

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

Is g++ misbehaving with function template overloading?

I took the following example from http://en.cppreference.com/w/cpp/language/function_template#Function_template_overloading
and clang (3.4) seems to be handling it just fine, while g++ (4.8.3) gives an 'ambiguous overload' error:
struct A {};
template<class T> struct B {
template<class R> void operator*(R&){ cout << "1" << endl; } // #1
};
template<class T, class R> void operator*(T&, R&) { cout << "2" << endl;} // #2
int main() {
A a;
B<A> b;
b * a; //prints 1
}
clang correctly prints 1 (as expected according to cppreference), while g++ gives this error:
test_templates.cpp: In function ‘int main()’:
test_templates.cpp:13:5: error: ambiguous overload for ‘operator*’ (operand types are ‘B<A>’ and ‘A’)
b * a; //prints 1
^
test_templates.cpp:13:5: note: candidates are:
test_templates.cpp:7:26: note: void B<T>::operator*(R&) [with R = A; T = A]
template<class R> void operator*(R&){ cout << "1" << endl; } // #1
^
test_templates.cpp:9:33: note: void operator*(T&, R&) [with T = B<A>; R = A]
template<class T, class R> void operator*(T&, R&) { cout << "2" << endl;} // #2
Is g++ actually misbehaving here?
This example is taken from the standard (this is the draft for c++11).
14.5.6.2 Partial ordering of function templates paragraph 3 example:
struct A { };
template<class T> struct B {
template<class R> int operator*(R&); // #1
};
template<class T, class R> int operator*(T&, R&); // #2
// The declaration of B::operator* is transformed into the equivalent of
// template<class R> int operator*(B<A>&, R&); // #1a
int main() {
A a;
B<A> b;
b * a; // calls #1a
}
So, the standard itself pretty much say this is legal code. I could copy-paste rules, but one might as well click link and jump to the relevant place. My point is only to prove this is a proper compilable code as defined by the standard.
For what it's worth on my debian clang 3.5.0 compiled it right away, clang 3.4.2 had to be executed with -std=c++11, g++ 4.9.1 reported ambiguity in all cases (I even tried 1y).
I am puzzled by clang behaviour, though. I thought it might have been ambiguous in earlier versions of c++, the rule to disambiguate was added as a part of c++11 and g++ didn't keep up. But clang 3.5 compiles it even with -std=c++98.
That call is ambiguos. GCC is right.
§13.5.2/1
Thus, for any binary operator #, x#y can be interpas either
x.operator#(y) or operator#(x,y). If both forms of the operator
function have been declthe rules in 13.3.1.2 determine which, if any,
interpretation is used.
And in this case, we do have both the member and nonmember function. The built-in version is not included because the left hand operator has class type.
If you called the operator explicitly, there would be no ambiguity. However, when the call is done through an operator (thus implicitly) there is nothing which can distinguish between member and nonmember, therefore they're both viable functions which, in this case, leads to an ambiguous function call.
Previous versions of clang report it as ambiguous as well: http://goo.gl/OWsJUv

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.