two nearly identical calls, one works one fails - c++

I have these template functions for use inline on device with cuda
template <class T> __device__ inline T& cmin(T&a,T&b){return (a<b)?(a):(b);};
template <class T> __device__ inline T& cmax(T&a,T&b){return (a>b)?(a):(b);};
In the code I have
cmin(z[i],y[j])-cmax(x[i],z[j])
for int arrays x,y,and z. I get the error:
error: no instance of function template "cmax" matches the argument list
argument types are: (int, int)
I get the error for cmax but not cmin. If I replace the cmax line with
#define cmax(a,b) ((a)>(b))?(a):(b)
that works just fine, but I don't want #defines, they are problematic. What the heck is going on here?
EDIT:
here is the full calling function. times is typedef int.
__global__ void compute_integral_y_isums(times * admit, times * discharge, times * Mx, times * isums, ar_size N){
// computes the sums for each j
// blocks on j,
// threads on i since we will be summing over i.
// sumation over J should be handled by either a different kernel or on the cpu.
ar_index tid = threadIdx.x;
ar_index i = blockIdx.x; // summing for patient i
ar_index j = threadIdx.x; // across other patients j
__shared__ times cache[threadsPerBlock];
times Iy = 0;
while(j<N){
// R code: max(0,min(Mx[i],d3[j,'Discharge.time'])-max(d3[i,'Admission.time'],Mx[j]))
times imin = cmin(Mx[i],discharge[j]);
times imax = cmax(admit[i],Mx[j]);
Iy += cmax(0,imin-imax);
j += blockDim.x;
}
cache[tid] = Iy;
__syncthreads();
// reduce
/***REMOVED***/
}

Iy += cmax(0,imin-imax);
is not legal. You can't bind the literal 0 to an int& reference (but you can to a const int& reference).

If either x or z is a const array, their element type will be const int, which is not convertible to int&.
Try with:
template<class T> __device__ inline T cmin(const T& a, const T& b)
{
return (a < b ? a : b);
}
template<class T> __device__ inline T cmax(const T& a, const T& b)
{
return (a > b ? a : b);
}
If T is always a primitive type like int, you can even pass the parameters by value:
template<class T> __device__ inline T cmin(T a, T b)
{
return (a < b ? a : b);
}
template<class T> __device__ inline T cmax(T a, T b)
{
return (a > b ? a : b);
}
EDIT: #aschepler has the right answer.

You should be careful in returning a reference, if your functions also take references as arguments. You might return a reference to a temporary! Like in:
cmin(0,imin-imax);
which is probably ok for int and float, but dangerous for non-PODs.

Try to reverse the definition order please.
template <class T> __device__ inline T& cmax(T&a,T&b){return (a>b)?(a):(b);};
template <class T> __device__ inline T& cmin(T&a,T&b){return (a<b)?(a):(b);};
cmax then cmin. What is the outpout then ?

Your cmax and cmin are taking non-const reference to the elements. Maybe your arrays are declared as const?
Hard to tell, because the example is not complete.

Maybe you already have some active defines which pollute you namespace?Try renaming cmin and cmax, or #undef cmin and #undef cmax. Or run g++ -E to see the de-macrofied code.
Or add :: namespace specifier:
::cmin(z[i],y[j])-::cmax(x[i],z[j])
Anyway, you only need all the () in defines. Nicer:
template __device__ T& cmin(const T&a,const T&b){return a<b?a:b;};
And you probably do not need the inline for a template function neither.

To clarify my comment on the initial question: Yes, one should be careful if ona just passes through a reference from a parameter. Here is a complete illustration:
#include <iostream>
struct Thing {
int data;
Thing() { data = 42; }
Thing(int val) { data = val; }
Thing(const Thing& oth) { data = oth.data; }
Thing& operator=(const Thing& oth)
{ if(this!=&oth) this->data = oth.data; return *this; }
~Thing() { data = 0; } // clear, destroy, release...
};
bool operator<(const Thing &a, const Thing &b) { return a.data
const T& refmin(const T &a, const T &b) // return a ref
{
return a < b ? a : b;
}
template
const T copymin(const T &a, const T &b) // return a copy
{
return a < b ? a : b;
}
followed by
int main(int argc, const char* [])
{
Thing a(11);
Thing b(88);
std::cerr << "Simple operation:" << std::endl;
const Thing c = a + b;
std::cerr << " c:" << c.data << " should be 99" << std::endl;
std::cerr << "Working on temp expression (BAD):" << std::endl;
const Thing &x = refmin(c, b-a); // '&x' will be gone after ';'
// the next line might crash:
std::cerr << " x:" << x.data << " should be 77" << std::endl;
std::cerr << "Working explicit side variable (OK):" << std::endl;
const Thing &d = b-a;
const Thing &y = refmin(c, d); // '&y' is now same as '&d'
std::cerr << " d:" << d.data << " should be 77" << std::endl;
std::cerr << " y:" << y.data << " should be 77" << std::endl;
std::cerr << "Working on a copy (OK):" << std::endl;
const Thing &z = copymin(c, b-a);
std::cerr << z:" << z.data << " should be 77" << std::endl;
return 0;
}
The output is:
$ ./minreftest
Simple operation:
c:99 should be 99
Working on temp expression (BAD):
x:0 should be 77
Working explicit side variable (OK):
d:77 should be 77
y:77 should be 77
Working on a copy (OK):
z:77 should be 77
On some machines it might even segfault, I guess. In Things destructor I reset data to 0, but one could easily imagine more there.
So, when we do the BAD refmin call, we return a reference to a temporary. Which is destroyed after the ;. So, when we try to output &x, it's already gone.

Related

Return type deduction failure in overloaded operator

So I have this class template with a single attribute value of type T where I try to overload the + operator, s.t. adding two objects of this class results in another object of this class where the value is the sum of the values of the two. Here's the code:
template<typename T>
class Number
{
public:
//constructors
Number(T value)
: value(value) {}
//attributes
const T value;
//operators
//addition +
template<typename U>
auto operator+(Number<U> other)
{
auto val = this->value + other.value;
Number output(val); //instantiating object of class Number, using constructor
std::cout << "output value: "<<output.value << std::endl;
std::cout << "auto val: "<< val << std::endl;
return output;
}
};
int main()
{
Number<int> x(2);
Number<float> y(2.5);
Number z=x+y;
std::cout << "x = " << x.value << std::endl;
std::cout << "y = " << y.value << std::endl;
std::cout << "x+y = " << z.value << std::endl;
return 0;
}
.
The output is:
output value:4
auto val: 4.5
x = 2
y = 2.5
x+y = 4
.
Obviously there occurs and undesired type conversion, from float to int and I am trying to find out how to avoid this without resorting to specialization. Explicit declaration of the operator output type does not compile. I understand that here the failure lies in that the auto type output becomes the type Number<T>, which in this case is Number<int> but does it have to be int even when a new object is instantiated within the operator definition scope { }?
I'd appreciate some help in this simple exercise, thank you in advance!
As #NathanPierson mentioned:
Number refers to Number<T> inside the operator. You unfortunately cannot use template argument deduction here.
The return type can be determined based on the type of the additon though. You could use a trailing return type to specify the return type. This assumes you don't need to use the result before returning from the function.
class Number
{
public:
...
template<typename U>
auto operator+(Number<U> other) -> Number<decltype(other.value + value)>
{
return {value + other.value};
}
};
.
You could also implement the operator in namespace scope:
template<class T, class U>
auto operator+(Number<T> const& s1, Number<U> const& s2)
{
auto val = s1.value + s2.value;
Number result(val);
return result;
}

How to overload call operator() function with same type and parameters, but different return type?

I want to define a new call operator() function with the parameters and type defined for the first operator() function. The reason for doing this is that the operations I want to perform with the new operator() function needs the same parameters as the first one, but maybe named differently but the type I need should remain the same. I know that it is not possible, but could someone suggest any different method to do this or are there any way around?
code listing:
namespace correlator {
class mean_square_displacement
{
public:
typedef std::shared_ptr<boost::multi_array<float, 2>> sample_type;
typedef double result_type; // fixed_vector<double, 3>
result_type operator() (sample_type const& first, sample_type const& second) const
{
double msd = 0;
size_t N = first->size(); // number of rows in one frame (11214 in one frame)
for (unsigned int i = 0; i < N; ++i) {
for (unsigned int j = 0; j < 3; ++j) {
double dr = (*first)[i][j] - (*second)[i][j];
msd += dr * dr;
//ofile_msd << i << " " << msd << std::endl;
if (msd > 0)
std::cout << "msd::" << msd << std::endl;
}
}
return msd/N;
} // first operator ends here
double operator()(sample_type const& first, sample_type const& second) const
{
std::cout << *(*first)[0][0] <<"The first element :." << std::endl;
return 0;
}
};
} // namespace correlator
Adapters:
struct Foo {
// these are your current operator() functions
int op1(int);
float op2(int);
};
struct FooAdapter1 {
Foo& foo;
auto operator()(int i) { return foo.op1(i); }
};
struct FooAdapter2 {
Foo& foo;
auto operator()(int i) { return foo.op2(i); }
};
So, instead of passing a Foo object like this:
std::invoke(foo,7); // no
You pass it via an adapter:
std::invoke(FooAdapter1{foo},7); // calls op1
And you give the Adapters good semantically sensible names, of course.
Alternatively, use an out argument to select the overload:
struct Foo {
// these are your current operator() functions
void operator()(int, int&);
void operator()(int, float&);
};
And then the somewhat ugly call:
float& result{};
std::invoke(foo,7,result); // selects the fist overload
You can't overload any function by changing only the return type.
Instead, you can use tag dispatching:
struct tag_a{};
struct tag_b{};
struct foo
{
int operator()(int, tag_a);
double operator()(int, tag_b);
};
// call example: f(4, tag_a());

Can't insert non-const value in unordered_map of references

I'm trying to create 2 std::unordered_map, one holds <A, int> and the second one holds <int&, A&>.
I'll explain at the end why I want to do this if you're curious.
My problem is that k_i has value of type std::reference_wrapper, k_i.insert doesn't work. But if I make k_i to have value std::reference_wrapper<const A>, the insert works.
I just can't figure out why is this and I am curious.
<<<<<Edit:
The thing is that find returns std::pair<const Ket, T> as stated by
Eljay in the comments. Because of this, the second std::unordered_map needs to have the value const.
<<<<<
Code:
Compiler: g++ version 10.1
Compile flags: -Wall -Wextra -std=c++20
#include <unordered_map>
#include <iostream>
#include <string>
#include <functional>
class A {
public:
A(const int x) : x(x) {
std::cout << "A::A(const int x) : x(" << x << ")\n";
}
A(const A& a) {
std::cout << "A::A {" << x << "} (const A& a {" << a.x << "} )\n";
x = a.x;
}
A(A&& a) {
std::cout << "A::A {" << x << "} (A&& a {" << a.x << "} )\n";
x = a.x;
}
A& operator=(const A& a) {
std::cout << "A::operator= {" << x << "} (const A& a)\n";
x = a.x;
return *this;
}
A& operator=(A&& a) {
std::cout << "A::operator= {" << x << "} (A&& a)\n";
x = a.x;
return *this;
}
~A() {
std::cout << "A::~A(" << x << ")\n";
}
friend std::ostream& operator<<(std::ostream& os, const A& dt);
int x;
};
std::ostream& operator<<(std::ostream& os, const A& dt) {
return os << dt.x;
}
template <typename K, typename V, typename... args>
void print_um(const std::unordered_map<K, V, args...> &umap) {
for (const auto &[x, y] : umap) {
std::cout << "(" << x << "," << std::ref(y).get() << "); ";
}
std::cout << "\n";
}
template <typename T>
struct MyHash {
std::size_t operator()(T const& s) const noexcept {
return std::hash<int>{}(std::ref(s).get());
}
};
template <typename T>
struct MyEquals {
constexpr bool operator()(const T &lhs, const T &rhs) const {
return lhs == rhs;
}
};
struct MyHash_A {
std::size_t operator()(A const& s) const noexcept {
return std::hash<int>{}(s.x);
}
};
struct MyEquals_A {
constexpr bool operator()(const A &lhs, const A &rhs) const {
return lhs.x == rhs.x;
}
};
int main() {
std::unordered_map<A, int, MyHash_A, MyEquals_A> k_s;
std::unordered_map<std::reference_wrapper<int>, std::reference_wrapper<const A>, MyHash<std::reference_wrapper<int>>, MyEquals<std::reference_wrapper<int>>> k_i;
{
A a(5);
std::cout << "1----\n";
k_s[a] = 12;
std::cout << "2----\n";
}
std::cout << "3----\n";
print_um<>(k_s);
std::cout << "4----\n";
A a(5);
std::cout << "5----\n";
auto it = k_s.find(a);
std::cout << "6----\n";
k_i.emplace((*it).second, (*it).first);
// // k_i[(*it).second] = ref_name;
std::cout << "7----\n";
print_um<>(k_s);
std::cout << "8----\n";
print_um<>(k_i);
std::cout << "9----\n";
int x = 12;
int &ref = x;
auto is_there = k_i.find(ref);
if (is_there != k_i.end()) {
std::cout << "elem: " << (*is_there).second.get() << "\n";
} else {
std::cout << "why? :(\n";
}
std::cout << "10---\n";
return 0;
}
As to why I create this code, I was thinking to be able to access some data by value or by key interchangeably (is there some better data structure? ). Like an username and a token, sometimes I have one, other times I have the other and using references I ensure that I don't waste space. Ofc, if one value has to change, I would invalidate the bucket position in the unordered_map because of the key, but I would treat that problem at a later date. Another motive is to learn some more C++ and test its limits (or mine).
From UnorderedAssociativeContainer requirements:
For std::unordered_map and std::unordered_multimap the value type is std::pair<const Key, T>.
In your code k_s is unordered_map<A, int>, so the value type is pair<const A, int>. In here:
auto it = k_s.find(a);
you get a "pointer" to such pair, and type of (*it).first is const A.
Your k_i is unordered_map<..., ref<A>> and when you do insert here:
k_i.emplace(..., (*it).first);
you essentially attempt to initialize ref<A> with const A, which obviously cannot work.
When you change k_i type to unordered_map<..., ref<const A>>, then you initialize ref<const A> with const A, which is fine.
Many have mentioned in the comment that Key type must be const. However the OP seems to wonder why the value type in k_i also need to be a const.
The reason for that is because you are referencing the key from k_s, which would be const A, and you can not reference it with a non-const reference.
To properly declare k_s, you might want to do something like:
std::unordered_map<
std::reference_wrapper<decltype(k_s)::value_type::second_type>,
std::reference_wrapper<decltype(k_s)::value_type::first_type>,
yourHash, yourComp
> k_s;
One alternative solution for you is to use another container that actually supports bidirectional lookup, such as Boost.Bimap.

Template parameters are arranged in the wrong order. Is it correct?

I expect the following output in the following program: 2 1.2. But the list of template parameters is reversed (as I understand). Should it be like that?
void print_id(int i, double d) noexcept {
std::cout << i << ' ' << d << std::endl;
}
template <typename G>
int mycode(G item, std::string & p) noexcept {
p.append((const char*)&item, sizeof(G));
return 1;
}
template<typename G>
const char* iterate(const char* &p) noexcept {
// std::cout << (typeid(G)).name() << " "; It gets know that the first type is 'double', the next is 'int'
const char* ans = p;
p += sizeof(G);
return ans;
}
template<typename ...T>
std::function<void(const char*)> state_f(void(*func)(T...)) {
return [func](const char* p) {
func(*(const T*)(iterate<T>(p))...);
};
}
template<typename ...T>
std::string encode(T... tpl) noexcept {
std::string s;
int crutch[] = { mycode<T>(tpl, s)... };
return s;
}
int main(void)
{
auto f = state_f(print_id);
f(encode(2, 1.2).c_str());
return 0;
}
I can reverse the parameters but I don't think it is correct.
The key lines in the shown code:
int crutch[] = { mycode<T>(tpl, s)... };
The parameter pack will expand, basically, to:
int crutch[] = { mycode<double>(1.3, s), mycode<int>(2, s) };
The implementation of mycode, to make a long story short, appends its argument to a buffer.
The issue here is that in this instance, C++ does not have a guaranteed evaluation order. Either function call may get executed first, and it may very well be different each time you run the same program. You are not guaranteed a left-to-right evaluation order, in this context. Either argument may end up being appended to the buffer, first.

Const operator overloading problems in C++

I'm having trouble with overloading operator() with a const version:
#include <iostream>
#include <vector>
using namespace std;
class Matrix {
public:
Matrix(int m, int n) {
vector<double> tmp(m, 0.0);
data.resize(n, tmp);
}
~Matrix() { }
const double & operator()(int ii, int jj) const {
cout << " - const-version was called - ";
return data[ii][jj];
}
double & operator()(int ii, int jj) {
cout << " - NONconst-version was called - ";
if (ii!=1) {
throw "Error: you may only alter the first row of the matrix.";
}
return data[ii][jj];
}
protected:
vector< vector<double> > data;
};
int main() {
try {
Matrix A(10,10);
A(1,1) = 8.8;
cout << "A(1,1)=" << A(1,1) << endl;
cout << "A(2,2)=" << A(2,2) << endl;
double tmp = A(3,3);
} catch (const char* c) { cout << c << endl; }
}
This gives me the following output:
NONconst-version was called - - NONconst-version was called - A(1,1)=8.8
NONconst-version was called - Error: you may only alter the first row of the matrix.
How can I achieve that C++ call the const-version of operator()? I am using GCC 4.4.0.
The overloading looks fine but you never call it on a const object. You can try this:
void foo(const Matrix& A) {
cout << "A(1,1)=" << A(1,1) << endl;
}
Matrix A(10,10);
foo(A);
This gives you:
- const-version was called - A(1,1)=0
The object you are calling the method on must be const, e.g.
cout << "A(2,2)=" << (*static_cast<const Matrix*>(&A))(2,2) << endl;
Generally, you can't call a const or non-const version of a function depending on what you do with the return value. If you want to emulate similar functionality, you can try returning some proxy that will switch the behaviour depending on what you do with it:
class Proxy
{
Matrix& m;
int x, y;
public:
...
// mutating operations
operator double&() { check(); return m.index(x,y); }
double& operator=(double d) { check(); return m.index(x,y)=d; }
// ... other mutating operations (+=, ...) analogously
// nonmutating ops
operator double() { return m.const_index(x, y); }
operator const double&() // ... same
};
Proxy Matrix::operator(int x, int y)
{
return Proxy(*this, x, y);
}
Assuming check() is your check for legal mutation (could be integrated in index()) and index() and const_index() are methods in Matrix that give a reference or const reference to a particular place.
Use const_cast<>() or make your instance const.
I'm guessing maybe you want to be sure the operator returns a const double? Maybe you should just provide the const version, not the other one.
You have different methods with different functionality, so give them different names. Then you don't need to have a const object just to call what you want.
You can still make operator() const call the alternative function in case you do happen have a const object. But the alternative functionality should be put in a function with a descriptive name.
As for getting a const handle to an object, use static_cast< const Matrix & >( A ).