I'm running a simple C++ program from HackerRank about pointers and it works fine on the website. However,
when I run it on MacOS, I get error: call to 'abs' is ambiguous and I'm not sure exactly what is ambiguous.
I've looked at other answers to similar issues, but the error message tends to be Ambiguous overload call to abs(double), which is not the issue I'm having, since I haven't used any doubles. I've also tried including the header files cmath and math.h, but the problem persists.
#include <stdio.h>
#include <cmath>
void update(int *a,int *b) {
int num1 = *a;
int num2 = *b;
*a = num1 + num2;
*b = abs(num1 - num2);
}
int main() {
int a, b;
int *pa = &a, *pb = &b;
scanf("%d %d", &a, &b);
update(pa, pb);
printf("%d\n%d", a, b);
return 0;
}
My issue occurs with line 8.
The full error message is:
$ clang++ test.cpp
test.cpp:8:10: error: call to 'abs' is ambiguous
*b = abs(num1 - num2);
^~~
.../include/c++/v1/math.h:769:1: note: candidate function
abs(float __lcpp_x) _NOEXCEPT {return ::fabsf(__lcpp_x);}
^
.../include/c++/v1/math.h:769:1: note: candidate function
abs(double __lcpp_x) _NOEXCEPT {return ::fabs(__lcpp_x);}
^
.../include/c++/v1/math.h:769:1: note: candidate function
abs(long double __lcpp_x) _NOEXCEPT {return ::fabsl(__lcpp_x);}
^
1 error generated.
The three overloads of abs that you have from <cmath> are abs(float), abs(double) and abs(long double); it's ambiguous because you have an int argument and the compiler doesn't know which floating-point type to convert to.
abs(int) is defined in <cstdlib>, so #include <cstdlib> will resolve your problem.
If you're using Xcode, you can get more details about the error in the Issues navigator (⌘5) and clicking the triangle next to your issue.
For me, #include <cstdlib> didn't solve the issue, maybe because I didn't have to include anything to use abs. So, in case it helps someone else, with explicit casting, it worked well for me like in the next code:
*b = abs(int(num1 - num2));
In templated code, it may be easily overlooked that std::abs is not defined for unsigned types. As an example, if the following method is instantiated for an unsigned type, the compiler may rightfully complain that std::abs is undefined:
template<typename T>
bool areClose(const T& left, const T& right) {
// This is bad because for unsigned T, std::abs is undefined
// and for integral T, we compare with a float instead of
// comparing for equality:
return (std::abs(left - right) < 1e-7);
}
int main() {
uint32_t vLeft = 17;
uint32_t vRight = 18;
std::cout << "Are the values close? " << areClose(vLeft, vRight) << std::endl;
}
A better definition of areClose() in above code, that would coincidentally also solve the problem of std::abs() being undefined, could look like this:
template<typename T>
bool areClose(const T& left, const T& right) {
// This is better: compare all integral values for equality:
if constexpr (std::is_integral<T>::value) {
return (left == right);
} else {
return (std::abs(left - right) < 1e-7);
}
}
if your using C compiler you should include
#include <stdlib.h>
and use abs without std::.
If you use C++ compiler then you should change abs to std::abs.
Hope it helps:)
I used #include <bits/stdc++.h> as the only include statement and it worked for me.
My code:
#include <bits/stdc++.h>
using namespace std;
class Solution {
public:
vector<int> findDuplicates(vector<int>& nums) {
int n = nums.size();
if(n == 0 || n == 1)
return {};
vector<int> ans;
for(int i = 0; i < n; i++)
{
if(nums[abs(nums[i])-1] < 0)
ans.push_back(abs(nums[i]));
else
nums[abs(nums[i])-1] = -1 * nums[abs(nums[i])-1];
}
return ans;
}
};
Related
I would like to write a function that wraps MPI_Allreduce, and which accepts any binary operator (as std::reduce) to be used as reduction operator by MPI. Especially, the user of such a function could use a lambda.
The following simple sample code illustrates that:
#include <mpi.h>
#include <iostream>
#include <functional>
template<typename BinaryOp>
void reduce(double *data, int len, BinaryOp op) {
auto lambda=[op](void *a, void *b, int *len, MPI_Datatype *){
double *aa=static_cast<double *>(a);
double *bb=static_cast<double *>(bb);
for (int i=0; i<*len; ++i) {
bb[i]=op(aa[i], bb[i]);
}
};
// MPI_User_function is a typedef to: void (MPI_User_function) ( void * a, void * b, int * len, MPI_Datatype * )
MPI_User_function *opPtr=/* black magic code that get the function pointer from the lambda */;
MPI_Op mpiOp;
MPI_Op_create(*opPtr, 1, &mpiOp);
MPI_Allreduce(MPI_IN_PLACE, data, len, MPI_DOUBLE, mpiOp, MPI_COMM_WORLD);
MPI_Op_free(&mpiOp);
}
int main() {
MPI_Init(nullptr, nullptr);
double data[4]={1.,2.,3.,4.};
reduce(data, 4, [](double a, double b){return a+b;});
int pRank;
MPI_Comm_rank(MPI_COMM_WORLD, &pRank);
if (pRank==0) {
for (int i=0; i<4; ++i) {
std::cout << data[i] << " ";
}
std::cout << std::endl;
}
MPI_Finalize();
return 1;
}
The missing part is the code that get a function pointer from the lambda in the reduce function. From several related questions, this problem of getting a function pointer from a capturing lambda seems to be tricky but possible to solve. But I failed to have something working on this simple code (I tried some tricks with std::function, std::bind, storage of the lambda in a static variable)... So a little help would be great!
EDIT: Following #noma answer, I tried the following simplified code without MPI in goldbolt
#include <iostream>
#include <functional>
typedef double MPI_Datatype;
template<typename BinaryOp, BinaryOp op> // older standards
void non_lambda(void *a, void *b, int *len, MPI_Datatype *)
{}
template<typename BinaryOp>
void reduce(double *data, int len, BinaryOp op) {
typedef void (MPI_User_function) ( void * a, void * b, int * len, MPI_Datatype * );
MPI_User_function *opPtr = &non_lambda<decltype(+op), +op>; // older standards;
}
int main() {
double data[4]={1.,2.,3.,4.};
reduce(data, 4, [](double a, double b){return a+b;});
return 1;
}
It compile on some compilers. Here are the results:
icc >= 19.0.1 (with -std=c++17) : OK
clang++ >= 5.0.0 (with --std=c++17): OK
clang++ 10.0.0 (with --std=c++14): NOK
g++ 9.3 (with --std=c++17): NOK
icc >= 19.0.0 (with -std=c++17) : NOK
The error message with icc 19.0.0 with -std=c++17 (or icc 19.0.1 with -std=c++14) is interesting:
<source>(15): error: expression must have a constant value
MPI_User_function *opPtr = &non_lambda<decltype(+op), +op>; // older standards;
^
detected during instantiation of "void reduce(double *, int, BinaryOp) [with BinaryOp=lambda [](double, double)->double]" at line 21
And indeed, I don't really understand the passing of the 'op' variable which is a runtime argument of the function reduce as the second template parameter of the non_lambda function... Is it an obscure c++17 functionality that only some of the compilers support?
I think the lambda approach is not possible here as it is a capturing lambda, see
https://stackoverflow.com/a/28746827/7678171
We can use a function template with the BinaryOp as a template value parameter instead of a Lambda here. This assumes that the BinaryOp is either a function pointer, or a capture-less lambda, that can be converted into one. Instead of the lambda inside your reduce we introduce:
template<auto op> // this is C++17, so use --std=c++17
// template<typename BinaryOp, BinaryOp op> // older standards
void non_lambda(void *a, void *b, int *len, MPI_Datatype *)
{
double *aa=static_cast<double *>(a);
double *bb=static_cast<double *>(bb);
for (int i=0; i<*len; ++i) {
bb[i]=op(aa[i], bb[i]);
}
}
The Black Magic line then is:
/* black magic code that get the function pointer from the lambda */
MPI_User_function *opPtr = &non_lambda<+op>; // NOTE: the + implies the lamda to function pointer conversion here
// MPI_User_function *opPtr = &non_lambda<decltype(+op), +op>; // older standards;
Hope this helps.
NOTE: I got this compiled using Clang 6.0, but g++ 7.5 failed (possible compiler bug?):
error: no matches converting function ‘non_lambda’ to type ‘void (*)(void*, void*, int*, struct ompi_datatype_t**)’
MPI_User_function *opPtr = &non_lambda<+op>;
^~~~~
note: candidate is: template<auto op> void non_lambda(void*, void*, int*, ompi_datatype_t**)
void non_lambda(void *a, void *b, int *len, MPI_Datatype *)
Maybe newer g++ versions work.
I have defined some static functions in their own .h and .cpp files, so these may be called from elsewhere without need for instantiation:
functions.h
#pragma once
class functions {
public:
static const int addition(const int&, const int&);
static const int product(const int&, const int&);
};
functions.cpp
#include "functions.h"
const int functions::addition(const int& op1, const int& op2) {
return op1 + op2;
}
const int functions::product(const int& op1, const int& op2) {
return op1 * op2;
}
I have also created a section for program settings where I will define which of the functions to pick:
constants.h
#pragma once
const int modulus = 10;
extern const int(*operation)(const int&, const int&);
constants.cpp
#include "constants.h"
#include "functions.h"
const int(*operation)(const int&, const int&) = &functions::addition;
This code works as expected using the following sample:
main.cpp
#include <iostream>
#include "constants.h"
int main() {
int a = 7, b = 4;
std::cout << operation(a,b) % modulus << std::endl;
}
Problem is, now I would like to parametrize the functions addition and product using a non-type template, such as:
functions.h
#pragma once
class functions {
public:
template<const int&> static const int addition(const int&, const int&);
};
functions.cpp
#include "functions.h"
template<const int& sub> const int functions::addition(const int& op1, const int& op2) {
return op1 + op2 - sub;
}
The later code breaks, no matter how I try to adapt the other files. I have done everything I reasonably (and pointlessly) could imagine.
Any help on how to rewrite the code on constants.* will be very appreciated.
Templates are instantiated at compile time, and for that the definition must be known - you need to have the template definition in the header.
Even if you do that, you don't have an int as the parameter but a const int&.
That means that you need to instantiate it with an lvalue whose identity (i.e. location) can be determined at compile-time.
In turn, that means that the parameter must be a variable with external linkage - not a temporary or a local variable.
In other words:
extern int x;
void foo()
{
addition<1>(2,3); // Not good; not an lvalue
const int y = 1;
addition<y>(2,3); // Not good; no linkage
addition<x>(2,3); // Good
}
You probably want to use template<int sub> instead.
(Another side note: const references to primitive types are pointless. All they do is add overhead.)
Template definitions should either be visible to the compiler during instantiation, or explicitly instantiated. Since I highly doubt you can explicitly instantiate all your possible versions of integer template, you have put the defginitons into the header.
Than comes the problem of operations. Since it's a function pointer, it can only point to specific instance of your template - the one instantiated with specific integer template. Doubt it's usable at all.
I suggest to rethink your design.
Created shared library with below file
example.cpp
#include <iostream>
template <typename T>
T Max (T & a, T & b)
{
return a < b ? b:a;
}
I was trying to use above library in my code
test.cpp
#include <stdio.h>
#include <iostream>
using namespace std;
template int Max <int> (int & a, int & b);
template double Max <double> (double & a, double & b);
int main ()
{
int i = 39;
int j = 20;
cout << "Max(i, j): " << Max(i, j) << endl;
double f1 = 13.5;
double f2 = 20.7;
cout << "Max(f1, f2): " << Max(f1, f2) << endl;
return 0;
}
when I compiled above code ,getting the following error
test.cpp:4: error: explicit instantiation of non-template ‘int Max’
test.cpp:4: error: expected ‘;’ before ‘<’ token
test.cpp:5: error: explicit instantiation of non-template ‘double Max’
test.cpp:5: error: expected ‘;’ before ‘<’ token
test.cpp: In function ‘int main()’:
test.cpp:11: error: ‘Max’ was not declared in this scope*
I realize this is a trivial example more for academic purpose than anything else. Otherwise I would recommend scrapping the whole thing and just using std::max from the get-go. The standard library provides a wealth of well-specified and tested functionality for the taking; use it unless you have a damn good reason to reinvent the wheel.
If you seriously want to provide a template declaration of a function in a header, and provide the implementation of said-template in a shared object library, you can do it by using explicit instantiation, which it appears you're attempting. However, your attempt appears to be putting said-same in the wrong module.
One way to do it is as follows:
example.hpp
#ifndef MYLIB_EXAMPLE_HPP
#define MYLIB_EXAMPLE_HPP
// define forward declaration here. no implementation
template<class T> T Max(T lhs, T rhs);
#endif
example.cpp
#include "example.hpp"
// provide implementation here
template<class T>
T Max(T lhs, T rhs)
{
return (lhs < rhs) ? rhs : lhs;
}
// explicit instantiations
template int Max<int>(int,int);
template double Max<double>(double,double);
That's it for the library. An example build using clang would be:
clang++ -std=c++11 -Wall -Wextra -pedantic -fPIC -shared -o libexample.so example.cpp
The resulting shared object library exposes the following symbols:
nm libexample.so
0000000000000f50 T __Z3MaxIdET_S0_S0_
0000000000000f20 T __Z3MaxIiET_S0_S0_
U dyld_stub_binder
so as you can see, they're there in the lib. On to the test program that will consume this library:
test.cpp
#include <iostream>
#include "example.hpp"
int main ()
{
int i = 39;
int j = 20;
std::cout << "Max(i, j): " << Max(i, j) << std::endl;
double f1 = 13.5;
double f2 = 20.7;
std::cout << "Max(f1, f2): " << Max(f1, f2) << std::endl;
return 0;
}
We build it as follows (assuming the library is in the local folder):
clang++ -std=c++11 -Wall -Wextra -pedantic -L. -o test -lexample test.cpp
The resulting program, test, produces the following output:
Max(i, j): 39
Max(f1, f2): 20.7
Honestly, there isn't a ton of value in doing it this way, as any future usages of Max that are not provided in your explicit list will result in linker errors (unless that is the intent, in which case it would do exactly what you're looking for).
My recomendations:
Change example.cpp to header a file, Max is a template function
Remove the forward declarations in the code
Remove #include <stdio.h>, unless that really is used somewhere
example.hpp:
template <typename T>
T Max (T& a, T& b)
{
return a < b ? b : a;
}
test.cpp:
#include <iostream>
using namespace std;
int main ()
{
int i = 39;
int j = 20;
cout << "Max(i, j): " << Max(i, j) << endl;
double f1 = 13.5;
double f2 = 20.7;
cout << "Max(f1, f2): " << Max(f1, f2) << endl;
return 0;
}
Tried to argument the std::string so that it supports method "bool operator==(int)". I got errors:
$ g++ -std=c++11 te2.cc
te2.cc: In function ‘int main(int, char**)’:
te2.cc:20:20: error: no matching function for call to ‘mstring::mstring(const char [4])’
te2.cc:20:20: note: candidates are:
te2.cc:10:7: note: mstring::mstring()
te2.cc:10:7: note: candidate expects 0 arguments, 1 provided
te2.cc:10:7: note: mstring::mstring(const mstring&)
te2.cc:10:7: note: no known conversion for argument 1 from ‘const char [4]’ to ‘const mstring&’
te2.cc:10:7: note: mstring::mstring(mstring&&)
te2.cc:10:7: note: no known conversion for argument 1 from ‘const char [4]’ to ‘mstring&&’
Here is the simple source:
#include <unordered_map>
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <iostream>
using namespace std;
class mstring : public string {
public:
//mstring (char* p) : std::string(p) {};
bool operator == (int x) {
int n = atoi(this->c_str());
return (n == x);
}
};
int main(int argc, char *argv[])
{
mstring t("123");
if (t == atoi(argv[1])) {
printf("yes\n");
} else {
printf("no\n");
}
}
If I uncomment the constructor /mstring (char* p) : std::string(p) {};, then it compiles and runs fine.
The question is, if it possible to make it work without defining the constructors for mstring, just use the whatever the constructors of the base class (there is no new data member anyway)? Thanks.
What about providing a free standing operator function instead of inheriting from std::string (which makes that code more usable overall):
bool operator==(const std::string& s, int i) {
int n = atoi(s.c_str());
return (n == i);
}
bool operator==(int i, const std::string& s) {
return s == i;
}
Or even more generic:
template<typename T>
bool operator==(const std::string& s, T t) {
std::istringstream iss;
iss << t;
return (s == iss.str());
}
Classes from the std namespace aren't intended to be inherited, but just used in interfaces and function parameters. Inheriting from those classes makes your code less usable, since clients need to use your implementation instead of just using the std type.
Also note: For your particular use case it's not necessary to convert anything at all, unless you want to assert that argv[1] contains a number (where atoi() certainly isn't the best method to do so, look up stoi() instead). You can just compare the strings:
if (std::string("123") == argv[1]) {
printf("yes\n");
} else {
printf("no\n");
}
you can explicitly inherit the constructors by adding
using string::string;
in your class
Alright so heres the program and works absolutely right
#include <iostream>
using namespace std;
template <typename T>
void Swap(T &a , T &b);
int main(){
int i = 10;
int j = 20;
cout<<"i, j = " << i <<" , " <<j<<endl;
Swap(i,j);
cout<<"i, j = " << i <<" , " <<j<<endl;
}
template <typename T>
void Swap(T &a , T &b){
T temp;
temp = a ;
a = b;
b= temp;
}
but when I change the function's name from Swap to swap
it generates an error saying
error: call of overloaded 'swap(int&, int&)' is ambiguous| note:
candidates are: void swap(T&, T&) [with T = int]| ||=== Build
finished: 1 errors, 0 warnings ===|
what happened is it a rule to start functions using templates to start with a capital letter ?
This is because there already exists a function called swap. It is actually under the std namespace, but because you have a using namespace std line, it exists without the std:: prefix.
As you can see, using the using namespace std isn't always a good option because of possible name collisions, as in this example. In general one should prefer not to use the using directive unless there's a real reason for this - namespaces exist for a reason - to prevent name collisions.