Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How properly pass comparator to another template function

Tags:

c++

templates

I need a function that will take two iterators and a custom comparator to compare values of this iterators. I don't want use additional template argument for this. I've implemented it in this way:

template<typename T>
void foo(T begin, T end,
  function<bool(decltype(*begin), decltype(*begin))> compare = less<decltype(*begin)>())
{
    // I want to use 'compare' as: "compare(*begin, *begin);"
}

This code has been compiled normally by clang, but on GCC 5.4.0 I've got some errors:

binary_heap.cpp:10:79: error: local variable 'begin' may not appear in this context
   function<bool(decltype(*begin), decltype(*begin))> compare = less<decltype(*begin)>())
                                                                               ^
binary_heap.cpp:10:85: error: template argument 1 is invalid
   function<bool(decltype(*begin), decltype(*begin))> compare = less<decltype(*begin)>())

How to correct this code so that it can be successfully compiled on both clang and GCC? Or maybe are there a more suitable solution for defining such function?

like image 957
0x1337 Avatar asked Jan 18 '26 15:01

0x1337


1 Answers

You cannot use a parameter in a default argument, even in an unevaluated context (although the Standard should probably be amended to loosen that restriction). Instead of decltype(*begin), use

decltype(*std::declval<T&>())

Edit: Actually, that probably doesn't do what you want, since if applying the * operator yields an lvalue, then the decltype specifier will resolve to an lvalue reference, but you would want the unreferenced type to be the argument to std::less. Better to use:

typename std::iterator_traits<T>::value_type

Edit 2: I agree with krzaq, it's better to just add another template parameter.

like image 153
Brian Bi Avatar answered Jan 20 '26 05:01

Brian Bi



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!