I'm trying to pass the boost::geometry::get function described here to another function, but I can't seem to get it right.
I have:
template<typename StorageType = double,
std::size_t D = 3>
class Derivative : public DerivativeBase<StorageType, D> {
public:
typedef typename DerivativeBase<StorageType, D>::results_t results_t;
template<typename Iterator, typename Geometry>
results_t operator()(Iterator& objIterator, StorageType (*getter)(Geometry const&))
...
and the compiler throws:
error: no match for call to ‘(Derivative<double, 3ul>) (iterator&, <unresolved overloaded function type>)’
I tried calling my function with:
derivs = myDerivs(it, &boost::geometry::get<0>);
I guess part of the issue is that since I don't pass an argument to get, the compiler can't figure out what type Geometry should be in the function signature.
How do I go about passing this function through?
This is entirely non-specific to boost.geometry. You need to static_cast the function to it's exact type if it is overloaded or you need to pass all template parameters explicitly. The second is the case here (e.g. &get<0, GeometryType>).
Related
I want to deduce the return type of a function coming as a template parameter. Consider the following code:
#include <type_traits>
struct Result {};
Result foo() { return Result{}; }
template<typename Factory>
void check(Factory) {
using ActualResult = typename std::result_of<Factory()>::type;
static_assert(std::is_same<Result, ActualResult>::value, "");
}
int main() {
check(foo);
}
This works as expected. However, if I change the parameter of check() to const Factory&, then it does not compile. The error from gcc is:
prog.cc: In instantiation of 'void check(const Factory&) [with Factory = Result()]':
prog.cc:14:14: required from here
prog.cc:9:66: error: function returning a function
using ActualResult = typename std::result_of<Factory()>::type;
^
prog.cc:10:65: error: function returning a function
static_assert(std::is_same<Result, ActualResult>::value, "");
^
What's the problem here? How can I make it work?
Functions (just like arrays) can neither be passed as prvalue arguments or returned as prvalues.
Therefore, template <typename Factory> void check(Factory), which takes a prvalue argument, will cause foo to decay to the function pointer, and check(foo) will cause Factory to be deduced as Result (*)(). Finally, result_of<Factory()> gives the result of calling the callable type that is the function pointer with no arguments.
When you change check to check(const Factory&), the function takes an lvalue, and so there is no decay, and Factory is deduced as the function type Result(). This is not a type that you are allowed to pass to result_of*, which requires either a callable type or a reference to a function. That is, you should use result_of<Factory&()> in that case.
*) In C++11. The rules for result_of may have been relaxed in later revisions, and C++17 deprecates result_of.
Suppose there is an overloaded function:
void overloaded(int) {}
void overloaded(void) {}
Because I don't want to (or can) write down the full function signature (like void(int) or void(void)) I need to get this signature using only the function name (overloaded) and
its argument type(s) (int or void).
I tried several approaches using decltype and friends, but unfortunately to no success.
So, in short, I need something like this:
cout << typeid(
get_overload(overloaded,(int)0))::type /* where the magic happens */
.name() << endl;
If you're allowed to use the name overloaded inside the type function, this will do:
template<typename... A>
using sig = decltype(overloaded(std::declval<A>()...))(A...);
sig<int> gives void(int), and sig<> gives void().
This is just a wrapper of tclamb's solution in a template alias.
I have a function template that extracts data from an image and copies it to a smaller array (which I call a Patch) the template function is called copyPatch. It is defined as:
template <class DestType, class SrcType, class Transformation>
bool copyPatch(Patch<DestType> &patch,
ImageData<SrcType>* src_data,
size_t src_ul_pix,
size_t src_ul_line)
Note: the Transformation parameter allows me to pass in a class that performs some transformation on the data. I call the template function as follows,
copyPatch<float, uint8_t, StraightCopy>(m_patch_data, m_data.t8u,
ul_pix, ul_line)
where m_patch_data is of type Patch<float> and m_data.t8u is a member of a union defined as follows:
union {
ImageData<uint8_t>* t8u;
ImageData<uint16_t>* t16u;
ImageData<int16_t>* t16s;
ImageData<uint32_t>* t32u;
ImageData<int32_t>* t32s;
// A bunch more of these
void* tvoid;
} m_data;
When I compile this I get the following error (that I've doctored a bit):
error: no matching function for call to:
copyPatch(Patch<float>&, ImageData<unsigned char>*&, size_t&, size_t&)’
copyPatch<float, uint8_t, StraightCopy>( m_patch_data, m_data.t8u, ul_pix, ul_line);
^
note: candidate is:
template<class DestType, class SrcType, class Transformation>
bool copyPatch(Patch<T>&, ImageData<SrcType>*, size_t, size_t)
template argument deduction/substitution failed:
To me, I don't see why the function didn't match. The only possible reason I can see is that for the 2nd parameter it wants a pointer (which is what I thought I was passing), but the calling code seems to be passing a reference to a pointer.
Compiler is g++ 4.8.1.
As pointed out in the comments the problem possibly with my Transformation (StraightCopy) which is defined as follows:
template<class Dest, class Src>
class StraightCopy {
public:
Dest operator()(Src s) { return static_cast<Dest>(s); }
};
I missed passing the parameters to my StraightCopy class.
Thanks to PlasmaHH for pointing me in the right direction. My transformation type (StraightCopy) needed parameters. So my call looks like:
copyPatch<float, uint8_t, StraightCopy< float, uint8_t > >( m_patch_data, m_data.t8u, ul_pix, ul_line);
Isn't that beautiful :o)
I have been playing around with variadic templates in the new c++ standard and came up with a map function (headers + using decs excluded):
template<typename T>
T square(T i)
{
return i * i;
}
template <typename T, typename... Ts>
const tuple<Ts...> map(const T f, const Ts...args)
{
return make_tuple(f(args)...);
}
int main(int c, char *argv[])
{
tuple<int, int> t;
int (*fp) (int) = square;
t = map(fp, 6, 8);
cout <<get<0>(t) <<endl;
cout <<get<1>(t) <<endl;
return 0;
}
Which works. As long as all the arguments are the same type for map. If I change the main to use a slightly more general form:
tuple<int, float> t;
t = map(square, 6, 8.0f);
gcc 4.4 reports:
In function ‘int main(int, char**)’:
error: no matching function for call to ‘map(<unresolved overloaded function type>, int, float)’
Any ideas how to make this work?
First, you can't pass around an unresolved function template as a pointer (or template parameter), you can only pass around instances of it. What that means is that your template's first argument is being passed as an int (*)(int) in this example, and it cannot call the float (*)(float) instantiation. I'm not sure of the best way to fix that, but anyway it's not technically what you asked about.
I don't have a compiler to test this on, but I think if you use std::function to infer the types that the function you are passing in wants, you might be able to cast the parameters to the function. Like this:
template<typename T, typename Ts...>
tuple<Ts...> map(std::function<T (T)> const &f, Ts... args) {
return make_tuple(static_cast<Ts>(f(static_cast<T>(args)))...);
}
See, I think you need to cast both the parameter (as a T) and the return type (as a Ts) for the function since it seems some implicit conversion rules are not working inside this template.
If my syntax doesn't work (it probably doesn't, the ...s are tricky when you don't have a compiler for them), it might be possible that you could rewrite this as a much more verbose function which unpacks each Ts before calling the function, and then builds up a tuple as it goes. I'm not sure if that is really necessary, but my feeling is that compiler support for all of the ... unpacking is a little spotty right now, so even if you come up with something that should work, I wouldn't be surprised if your compiler couldn't handle it.
I have a member function of a template class declared as such:
template <class T>
int Data<T>::getPosition(vector<T> stuff, T newStuff, bool ascending)
I call this somewhere with the line
frequencies.insert(frequencies.begin() + getPosition(frequencies, current, ascending),
frequencies[i]);
The variables for that line are declared as:
vector<T> temp;
vector<int> frequencies;
int current = frequency.find(words[i])->second;
However, the call to getPosition gives this error:
Data.h|158|error: no matching function for call to 'primitives::Data<double>::getPosition(std::vector<int, std::allocator<int> >&, int&, bool&)'|
Data.h|165|note: candidates are: int primitives::Data<T>::getPosition(std::vector<T, std::allocator<_CharT> >, T, bool) [with T = double]|
What am I doing wrong here?
getPosition takes three arguments of type vector<T>, T and bool. The templated type T in this case is double (as is shown in the error message), and yet you are trying to pass vector<int> and int as the first and second argument, respectively.
Perhaps the parameters for getPosition should not be templated? Depends on what you are trying to achieve - you do have hard-coded int-vectors there, after all.
Your function prototype gets templated on Data<t>, and it looks like you're performing this call on an object with type Data<double> and passing a std::vector<int> and an int, when it probably expects a std::vector<double> and a double to correspond to the initial templated type of the Data object.
vector<T> temp;
Shouldn't T here be some type like int, double or bool?