template type deduction failing (std::empty as a predicate)

梦想的初衷 提交于 2019-12-04 11:18:12

Unfortunately there is a problem to distinguish overloaded template functions as std::all_of is also a template function. Better explaination: std::function fails to distinguish overloaded functions

So to do this, a static_cast to the correct function type: bool ( * )( const std::vector< int >& ) is required:

std::all_of( vv.begin(), vv.end(),
             static_cast< bool ( * )( const std::vector< int >& ) >( std::empty ) );

Using knowledge about the required static_cast we can make a helper template function to deduce the correct definition from the container type:

The helper function:

template< typename C >
inline auto overloaded_pred_for( const C&, bool ( *f )( const C& ) ) -> decltype( f )
{
    return f;
}

Example of it's usage:

std::all_of( vv.begin(), vv.end(), 
             overloaded_pred_for( std::vector< int >(), std::empty ) );

fast workaround

#include <algorithm>
#include <vector>

int main() {
   std::vector<std::vector<int>> vv;

   std::all_of(std::begin(vv), std::end(vv), 
    [](const auto &v) {return std::empty(v);});
}

what i the easiest way to workaround this?

Maybe

std::all_of(std::begin(vv), std::end(vv),
            [](auto const & v){ return v.empty(); });

?

std::empty is a function template, and as such not a callable object in and of itself. By explicitly providing the template parameters, you turn the function template name into a concrete instantiation, which is callable:

#include <algorithm>
#include <iterator>
#include <vector>

int main()
{
   std::vector<std::vector<int>> vv;

   std::all_of(std::begin(vv), std::end(vv), std::empty<std::vector<int>>);
}

Live demo (which incidentally crashes the compiler). Also note this GCC version apparently needed an #include <iterator> even though it is explicitly mentioned std::empty should come in with e.g. #include <vector>...

The problem is that there is not such a thing as std::empty, it's a member function as far as I know. Try using [](const auto& i){ return i.empty(); } instead.

EDIT: well, I haven't seen std::empty before but as the commenter below pointed out it exists, but still you can use the lambda

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!