I have a template overload operator defined like this:
enum E1 {e1};
enum E2 {e2};
template <typename T, e1> void operator<<(T& t, int i){ t += i;}
template <typename T, e2> void operator<<(T& t, int i){ t -= i;}
double d = 0;
It's good if i invoke the operator this way (which looks sucky)
operator<< <double, e1> (d, 3);
but syntax error if i invoke it this way:
d << <double, e1> 3;
How to rewrite the second form to make it work? Thank you!
Related
I have a problem with a Template function inside a class. When I call "Set" in something() function, VS show me:
Error C2275 'T': illegal use of this type as an expression
The header is:
#include <vector>
#include <array>
#include <iostream>
using t_double = double;
template<typename T>
using t_vec = std::vector<T>;
class SuperPixel2
{
t_vec<double> distances;
template<typename T>
void Set(t_vec<T> &v,
size_t i,
size_t j,
const T &val);
void something();
}
And the cpp file:
#include "SuperPixel2.h"
template<typename T>
void SuperPixel2::Set(t_vec<T> &v,
size_t i,
size_t j,
const T &val)
{
v[i * cols + j] = T;
}
void SuperPixel2::something()
{
t_double d;
//..
Set(distances, k, l, (t_double)d);
//..
}
In addition to what sudo make install said, you generally cannot declare a template in a header file and write the implementation in a cpp file. See here for an answer to your problem.
Well this line looks pretty odd:
v[i * cols + j] = T;
I think it's meant to be:
v[i * cols + j] = val;
As a side note (and maybe this would make more sense looking at the whole class), the type of distances is known (a vector of doubles), so it's unclear to me why the Set method needs to be a templated member.
In the following code, I wanted to achieve the effect of binary operator chaining for the specific type definition I want to use - for trivial operator chaining, that a binary operator returns the same type of object, most of cases just simply returning *this, which could trivially be used again to chain the next object of the same type.
However, in my case, the binary operators takes two reference_wrappers of two same typed objects (awaitable<T>::ref) as input, and returns an aggregated object of type (awaitable<awaitable<T>::ref>), and I wanted to use the returned aggregate object to chain the next awaitable<T>::ref and again return the further aggregated object of type awaitable<awaitable<T>::ref> - notice that the returned object is always the same type of awaitable<awaitable<T>::ref>, no matter how many more chaining happens.
The friend operator with template template parameter defined at location (XXX) hoped to serve this purpose, but compilers don't seem to be willing to perform the bind.
Could anyone shed some lights on how I can achieve the result as described?
Thanks!
#include <functional>
template <typename T>
struct awaitable
{
typedef std::reference_wrapper<awaitable> ref;
// (A) - okay
friend awaitable<ref> operator||(ref a1, ref a2)
{
awaitable<ref> r;
return r;
}
// (XXX) - this doesn't bind
template < template <typename> class _awaitable >
friend awaitable<ref> operator||(typename awaitable<typename _awaitable<T>::ref>::ref a1, ref a2)
{
awaitable<ref> r;
return r;
}
};
int main(int argc, const char * argv[])
{
awaitable<void> a1;
awaitable<void> a2;
auto r1 = a1 || a2; // Okay - r1 is of type awaitable<awaitable<void>::ref>
awaitable<void> a3;
auto r3 = r1 || a3; // doesn't bind to the operator defined at XXX
return 0;
}
[EDIT] -
Answers in this post and this seem to explain the situation pretty nicely, but in my case, the friend operator has a template template parameter (which is needed to avoid recursive template instantiation), which might prevent the compilers to generate the correct namespace scope function when the template is instantiated?
It seems that the friend function with template template parameter makes template deduction fail. The solution is to remove the template template parameter, and expand the ::ref usage to std::reference_wrapper within the friend function definition:
#include <functional>
template <typename T>
struct awaitable
{
typedef std::reference_wrapper<awaitable> ref;
// (A) - okay
friend awaitable<ref> operator||(ref a1, ref a2)
{
awaitable<ref> r;
return r;
}
// (XXX) - removing the template template parameter makes the template instantiation for a specific type T to generate a namespace version of the function!
friend awaitable<ref> operator||(std::reference_wrapper<awaitable<std::reference_wrapper<awaitable<T>>>> a1, ref a2)
{
awaitable<ref> r;
return r;
}
};
// template <typename T>
// awaitable<typename awaitable<T>::ref> operator||(typename awaitable<typename awaitable<T>::ref>::ref a1, typename awaitable<T>::ref a2)
// {
// awaitable<typename awaitable<T>::ref> r;
// return r;
// }
int main(int argc, const char * argv[])
{
awaitable<void> a1;
awaitable<void> a2;
auto r1 = a1 || a2; // Okay - r1 is of type awaitable<awaitable<void>::ref>
awaitable<void> a3;
auto r3 = r1 || a3; // now it works!
return 0;
}
Demo here
is this what you need?
template < template <typename> class _awaitable, typename U >
friend auto operator||(_awaitable<std::reference_wrapper<U>> a1, ref a2)
{
awaitable<ref> r;
return r;
}
live demo
EDIT1
I saw your answer where you removed the template parameter to get it working. That works great if void is the only the type you use. If you try to use another type it will fail though. The closest I've got to get around it is explicity using std::ref(r1) e.g.
template<typename U>
friend awaitable<ref> operator||(std::reference_wrapper<awaitable<std::reference_wrapper<awaitable<U>>>> a1, ref a2)
{
std::cout << "(XXX2)" << std::endl;
awaitable<ref> r;
return r;
}
awaitable<int> a4;
auto r4 = std::ref(r1) || a4;
live demo 2
For Learning Purposes:
I am creating a small numerical methods library and I am trying to implement the gradient currently I have done 2D gradient and 3D gradient . But I want to generalize this to higher dimensions.
Currently I have :
matrix<double> analysis::gradient_2D(std::function<double(double, double)> fn, double x, double y)
{
matrix<double> R(2, 1);
std::function<double(double)> fnX = [fn, y](double xVar){ return fn(xVar, y); };
std::function<double(double)> fnY = [fn, x](double yVar){ return fn(x, yVar); };
R(1, 1) = differentiateBest(fnX, x);
R(1, 2) = differentiateBest(fnY, y);
return R;
}
matrix<double> analysis::gradient_3D(std::function<double(double, double, double)> fn, double x, double y, double z)
{
matrix<double> R(3, 1);
std::function<double(double)> fnX = [fn, y, z](double xVar){ return fn(xVar, y,z); };
std::function<double(double)> fnY = [fn, x, z](double yVar){ return fn(x ,yVar, z); };
std::function<double(double)> fnZ = [fn, x, y](double zVar){ return fn(x, y, zVar); };
R(1, 1) = differentiateBest(fnX, x);
R(1, 2) = differentiateBest(fnY, y);
R(1, 3) = differentiateBest(fnZ, z);
return R;
}
// Where
double analysis::differentiateBest(std::function<double(double)> fn, double x)
{
return derivative_1_Richardson_6O(fn, x);
}
// For brevity , derivative_1_Richardson_6O also has the same input as differentiateBest
I know it is verbose , but I like it
Question
What I would like to do is to create a
// What do I do at the ... ?
matrix<double> analysis::gradient_ND(std::function<double(...)> fn, matrix<double>)
So that I can pass a std::function with arbitrary input say N and I will pass
a vector which has N values.
How will I go about doing this ? If the answer is too long , links will be appreciated too .
Thank you.
PS: I saw a method using Templates , but if I use templates in the implementation , the I will have to change the .cpp file to something else right ? I would like to avoid. If using templates is the only way , then I will have to compromise. Thanks.
template<class T>
struct array_view {
T* b = nullptr; T* e = nullptr;
T* begin() const { return b; }
T* end() const { return e; }
size_t size() const { return end()-begin(); }
bool empty() const { return begin()==end(); }
T& front()const{return *begin(); }
T& back()const{return *std::prev(end()); }
T& operator[](size_t i)const{return begin()[i]; }
array_view( T* s, T* f ):b(s),e(f) {};
array_view() = default;
array_view( T* s, size_t l ):array_view(s, s+l) {}
using non_const_T = std::remove_const_t<T>;
array_view( std::initializer_list<non_const_T> il ):
array_view(il.begin(), il.end()) {}
template<size_t N>
array_view( T(&arr)[N] ):array_view(arr, N){}
template<size_t N>
array_view( std::array<T,N>&arr ):array_view(arr.data(), N){}
template<size_t N>
array_view( std::array<non_const_T,N> const&arr ):
array_view(arr.data(), N){}
template<class A>
array_view( std::vector<T,A>& v):
array_view(v.data(), v.size()){}
template<class A>
array_view( std::vector<non_const_T,A> const& v):
array_view(v.data(), v.size()){}
};
an array_view is a non-owning view into a contiguous array of T. It has converting constructors from a myriad of contiguous containers (if matrix is contiguous, a converter to array_view should be written).
Then:
matrix<double> analysis::gradient_ND(std::function<double(array_view<const double>)>, array_view<const double> pt)
is reasonable.
Using array_view causes no problem with .h and .cpp code splitting. The only templates involved are either fixed (the array_view itself), or are resolved when constructing the array_view.
matrix<double> R(pt.size(), 1);
auto make_tmp = [pt]{
std::vector<double> tmp;
tmp.reserve(pt.size());
for (double x:pt)
tmp.push_back(x);
return tmp;
};
std::vector<std::function<double(double)>> partials;
partials.reserve(pt.size());
for (size_t i = 0; i < pt.size(); ++i) {
partials.push_back(
[&,i](double x){ auto tmp=make_tmp(); tmp[i]=x; return fn(tmp); };
);
}
for (size_t i = 0; i < pt.size(); ++i) {
R(1, i) = differentiateBest(partials[i], pt[i]);
}
return R;
note that creating array of partials is not actually needed. You could just directly differentiateBest.
There is an inefficiency where partials reallocate each call. If you are ok with making reentrancy not work (which will often be ok), creating a tmp and capturing it by-value, and modifying and restoring it after each call to fn, would boost performance.
[&,i,tmp=make_tmp()](double x){ std::swap(tmp[i],x); double r=fn(tmp); std::swap(tmp[i],x); return r; };
is C++14 version. C++11 version would create a tmp variable and capture it by-value.
I have re-arranged an example regarding the std::forward with template.
I have used a wrapper function and everything is fine, if i declare it as void function. It works as expected.
#include<iostream>
using namespace std;
template <typename T, typename U>
auto summation(T const &a, U const& b) -> decltype(T{}, U{}) {
cout << "call by lvalue" << endl;
return a+b;
}
template <typename T, typename U>
auto summation(T&& a, U && b) -> decltype(T{},U{}) {
cout << "call by rvalue" << endl;
return a+b;
}
template<typename T,typename U> void func(T&& a, U && b) {
summation(forward<T>(a), forward<U>(b));
}
int main() {
int x = 10;
double y = 20;
func(x,y);
func(10,20);
}
but if I want to return a type from a wrapper function, no matter what I used, I got error on lvalues function call ONLY, fund(x,y), stating "....function does not match the arguments"... the other fund(10,20) works.
template<typename T,typename U> auto func(T&& a, U && b) -> decltype(T{}, U{}) {
return summation(forward<T>(a), forward<U>(b));
}
and even using c++14 decltype(auto) for deducing the return type of forwarding functions and similar wrappers
template<typename T,typename U> decltype(auto) func(T&& a, U && b) {
return summation(forward<T>(a), forward<U>(b));
}
it does not work either, stating "decline(type) is C++o1 extension..." that, thank you compiler, but it does help.
One non sense horrible solution is declare the return type or T or U as return type. This compiles even if I got a warning stating "Reference to stack memory associated to local variable returned"
template<typename T,typename U> U func(T&& a, U && b) {
auto res = summation(forward<T>(a), forward<U>(b));
return res;
}
the return type of std::forward given (t) the object to be forwarded is
static_cast<T&&>(t)
therefore it the first solution with auto should work but it does not.
Any suggestion on this ?
Thanks for any help
decltype means the type of the expression given in its argument. So
decltype(T {}, U {})
will be the type of the expression T{}, U{}. You have the comma operator here, and so the type of the expression is the type of the expression after the comma, which is U{}, hence decltype (T{}, U{}) gives you type U (more precisely, U &&, I guess, since it is an rvalue).
What you want is
decltype(T{} + U{})
or
decltype(a+b)
(thanks to Jonathan Wakely, see comments).
I noticed, that in [24.4.7] of the last C++-Std Doc N3291 max ist not constexpr:
template<class T> const T& max(const T& a, const T& b);
Therefore, it is not allowed to use it in a static_assert for example. Correct?
static_assert( max(sizeof(int),sizeof(float)) > 4, "bummer" );
That is correct.
I imagine the reason is simply that std::max calls T::operator< for an arbitrary type T and for std::max to be constexpr, it would require T::operator< to be constexpr, which is unknown.
This is correct; std::min and std::max are not constexpr, not even in the latest draft of C++14 (N3690), so they cannot be used within constant expressions.
There is no good reason for this, only bad reasons. The most significant bad reason is that the C++ committee is composed of individuals who have a limited amount of time to work on standardization, and no-one has put in the work required to make these functions constexpr yet.
Note N3039, a change to the C++ standard adopted in 2010, that slightly extended the constexpr facility specifically so that function such as min and max could be made constexpr.
You can work around this by defining your own min and max functions:
template<typename T>
constexpr const T &c_min(const T &a, const T &b) {
return b < a ? b : a;
}
template<typename T, class Compare>
constexpr const T &c_min(const T &a, const T &b, Compare comp) {
return comp(b, a) ? b : a;
}
template<typename T>
constexpr const T &c_min_impl(const T *a, const T *b) {
return a + 1 == b ? *a : c_min(*a, c_min_impl(a + 1, b));
}
template<typename T>
constexpr T c_min(std::initializer_list<T> t) {
return c_min_impl(t.begin(), t.end());
}
// ... and so on
this works on c++ 11
template<const Sz a,const Sz b> constexpr Sz staticMax() {return a>b?a:b;}
use:
staticMax<a,b>()
and of course a and b must be constexpr