count_if()

Hello forum,

I am having the compiler error while trying the following code:

 
int left_child_count = (int) std::count_if( (m_objects.begin() + left_index),(m_objects.begin() + mid_point) ,isSameType);


The m_objects is of following type:

 
std::vector<Intersectable*> m_objects;


And the declaration and definition of the comparing function is as follows:

1
2
3
4
5
6
7
8
9
10
11
bool isSameType(Intersectable *intersectable);

bool BVHAccelerator::isSameType(Intersectable *intersectable)
{
    Intersectable *l_Intersectable = 0;

    if(typeid(*l_Intersectable) == typeid(*intersectable))
        return true;
    else
        return false;
}



But i am getting the following error :

 
/home/studenter/sajis997/adaptation/lab1/src/bvhaccelerator.cpp:154: error: argument of type ‘bool (asr::BVHAccelerator::)(asr::Intersectable*)’ does not match ‘bool (asr::BVHAccelerator::*)(asr::Intersectable*)’



I hope some one in the forum will help me to find the problem in my code


Thanks
Sajjad
Is BVHAccelerator a namespace? Is isSameType declared inside BVHAccelerator?
No it is not a namespace, it is a class .

And isSameType is declared inside the BVHAccelerator as follows:

1
2
3
4
5
6
7
8
9
10
11
bool BVHAccelerator::isSameType(Intersectable *intersectable)
{
    Intersectable *l_Intersectable = 0;

    if(typeid(*l_Intersectable) == typeid(*intersectable))
        return true;
    else
        return false;
}

I don't think you can use a non-static member function with std::count_if.
ummm, show me the exact line for wich the compiler says is wrong, 'cos i don't realy know where than 'non-matching' happens
I tried by making the matching function static as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
static bool isSameType(Intersectable *intersectable);


    bool BVHAccelerator::isSameType(Intersectable *intersectable)
    {
        Intersectable *l_Intersectable = 0;

        if(typeid(*l_Intersectable) == typeid(*intersectable))
            return true;
        else
            return false;
    }



And it worked.

Is there any reference to this information that you gave me, any book ?

Thanks for the effort.


Regards
Sajjad
If the method will not use the internal state of the object, then it should be static. Or shouldn't be a method but a function.

About your issue. You could say that these are equivalent *
1
2
3
4
5
6
7
8
9
10
11
struct foo{
  int value;
  void set(int v){ value=v; }
};

struct foo{
  int value
};
void set(foo *this, int v){
  this->value = v;
}
So as you can see, the function expects 2 arguments

http://cplusplus.com/reference/algorithm/count_if/
pred Unary predicate taking an element in the range as argument

¿Do you understand why it failed?

* Taked from Deep C (and C++) by Olve Maudal and Jon Jagger


Edit: being a template parameter, pred could be and object that has implemented operator()
Last edited on
Function adaptors (like mem_fun) as well as binders (like bind2nd) are deprecated.
Prefer using std::bind / std::function<> instead.
http://en.cppreference.com/w/cpp/utility/functional/bind
http://en.cppreference.com/w/cpp/utility/functional/function

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
#include <algorithm>
#include <functional>

struct A
{
    int div = 7 ;
    bool divisible( int arg ) const { return arg%div == 0 ; }
};

int main()
{
    using namespace std ;
    using placeholders::_1 ;
    int seq[] = { 23, 42, 13, 91, 14, 72, 53 } ;
    A aa ;
    cout << count_if( begin(seq), end(seq), bind( &A::divisible, aa, _1 ) ) << '\n' ;
}
It's going to be a couple of years more before I only recommend C++11 features.
Deprecated is defined by the IS as: Normative for the current edition of the Standard, but not guaranteed to be part of the Standard in future revisions.

As such, it sends a clear message to programmers: Do not use this feature anymore in any new code that you write. However if you already have legacy code that uses this feature, you have time to fix it: it will continue to work as it did before atleast till the next revision of the standard.

Ideally, programmers would compile their code with warnings enabled and compilers would convey this message to the programmer with a diagnostic. But the mileage varies.

Deprecation of a feature has nothing to do with it not being an 'only C++11 feature'. Almost all of the C++98 features are also non-deprecated C++11 features - std::rand() is not deprecated even though C++11 has <random>; std::pair<> is not deprecated even though C++11 has std::tuple<>.

The following is pure C++98 code. But it contains several constructs that were deprecated by the IS for C++98:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
#include <strstream> // warning: deprecated
#include <stdio.h> // warning: deprecated

int main()
{
    bool b = false ; ++b ; // warning: deprecated

    register int r = 0 ; // warning: deprecated

    char* p1 = "abcd" ; // warning: deprecated
    wchar_t* p2 = L"abcd" ; // warning:  deprecated

    char buffer[1024] ;
    std::ostrstream stm( buffer, sizeof(buffer) ) ; // warning: deprecated
}


g++ generates the following warnings:
warning: This file includes at least one deprecated or antiquated header
which may be removed without further notice at a future date.
Please use a non-deprecated interface with equivalent functionality instead.
For a listing of replacement headers and interfaces, consult the file backward_warning.h.
To disable this warning use -Wno-deprecated.

warning: deprecated conversion from string constant to 'char*'

warning: deprecated conversion from string constant to 'wchar_t*'


clang also warns about:
warning: incrementing expression of type bool is deprecated


Deprecation of a feature has nothing to do with it not being an 'only C++11 feature'.


Nobody said or implied that it did. Many people are using compilers that don't support features required by C++11 where the corresponding (replaced) pre-C++11 feature is deprecated. So, it doesn't necessarily make sense to recommend them until such features are more widely implemented.


> Many people are using compilers that don't support features required by C++11 where the
> corresponding (replaced) pre-C++11 feature is deprecated.
> So, it doesn't necessarily make sense to recommend them until such features are more widely implemented.

Agreed.

This is C++98-compatible code that uses deprecated features.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
#include <algorithm>
#include <functional>

struct A
{
    A( int i = 7 ) : div(i) {}
    int div ;
    bool divisible( int arg ) const { return arg%div == 0 ; }
};

int main()
{
    int seq[] = { 23, 42, 13, 91, 14, 72, 53 } ;
    enum { N = sizeof(seq) / sizeof(seq[0]) } ;
    A aa ;
    std::cout << std::count_if( seq, seq+N,
                    std::bind1st( std::mem_fun_ref(&A::divisible), aa ) ) << '\n' ;
}


This too is C++98-compatible code with equivalent functionality:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
#include <algorithm>

struct A
{
    A( int i = 7 ) : div(i) {}
    int div ;
    bool divisible( int arg ) const { return arg%div == 0 ; }
};

struct is_divisible
{
    explicit is_divisible( const A& aa ) : a(aa) {}
    bool operator() ( int arg ) const { return a.divisible(arg) ; }
    const A& a ;
};

int main()
{
    int seq[] = { 23, 42, 13, 91, 14, 72, 53 } ;
    enum { N = sizeof(seq) / sizeof(seq[0]) } ;
    A aa ;
    std::cout << std::count_if( seq, seq+N, is_divisible(aa) ) << '\n' ;
}


While using compilers that don't support features required by C++11, one can still write code that eschews deprecated features.
Last edited on
...yes, but at the expense of re-writing the stuff you are avoiding.

Personally, I like std::function<>; I think it is about time there was a superior solution.

However, it is easy enough to do a simple mass-swap of "mem_fun" to "function" when the time comes.

In the meantime, I'm going to let people's compilers catch up before I start recommending stuff that will confuse the newbies even more than than they already are and require them to do a lot of extra work to figure it out.
> ... confuse the newbies even more than than they already are ..

It is a moot point which of the following two snippets - one that uses deprecated features or the one that does not - will confuse a newbie 'even more'.

1
2
3
4
5
6
7
8
9
10
#include <cstring>
#include <algorithm>
#include <functional>

void replace_cstrs( const char* srce[], std::size_t n, const char* dest[],
                     const char* old, const char* replacement )
{
    std::replace_copy_if( srce, srce+n, dest,
        std::not1( std::bind2nd( std::ptr_fun(std::strcmp), old ) ), replacement ) ;
}


1
2
3
4
5
6
7
8
9
10
11
12
13
#include <cstring>
#include <algorithm>

struct cstr_equals
{
    explicit cstr_equals( const char* bb ) : b(bb) {}
    bool operator() ( const char* a ) const { return std::strcmp(a,b) == 0 ; }
    const char* b ;
};

void replace_cstrs( const char* srce[], std::size_t n, const char* dest[],
                     const char* old, const char* replacement )
{ std::replace_copy_if( srce, srce+n, dest, cstr_equals(old), replacement ) ; }


Note: this example was originally presented by Andy Koenig.
I don't think throwing extra confusion into the argument proves your point. The std::replace_copy_if() function is overused simply because they forgot to put copy_if() into the STL the first time around, and it makes everyone's head spin to play with double negatives.
My point is an extremely simple one: a deprecated feature should not be used if it can be avoided. And I would not recommend the use of a deprecated feature to any one.

I have nothing more to add.
Topic archived. No new replies allowed.