std::tr1::bind + for_each

Hello, i want to make a nested bind, but have compiler errors:

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

int _tmain(int argc, _TCHAR* argv[])
{
    void* p[] = { (void*)1, (void*)2, (void*)3 };

    std::tr1::shared_ptr < void > s((void*)NULL,
        std::tr1::bind(&std::for_each < void**, void (__cdecl *) (void*) >,
        p, p + 3,
            std::tr1::bind(&::operator delete, std::tr1::placeholders::_1)));

	return 0;
}


Output:
c:\program files\microsoft visual studio 9.0\vc\include\xxbind1(290) : error C2784: '_Ret std::tr1::_Callable_fun<_Ty,_Indirect>::_ApplyX(const _Arg0 &,_Arg1 &,_Arg2 &) const' : could not deduce template argument for '_Arg2 &' from 'void'
        with
        [
            _Ty=void (__cdecl *(__cdecl *const )(void **,void **,void (__cdecl *)(void *)))(void *),
            _Indirect=false
        ]


But with 'free' its works:

1
2
3
4
    std::tr1::shared_ptr < void > s((int*)NULL,
        std::tr1::bind(&std::for_each < void**, void (__cdecl *)(void*) >,
        p, p + 3,
            free));


and next bind with 'delete' works:

std::tr1::bind(&::operator delete, std::tr1::placeholders::_1)((void*)0);

How to make a right bind of template std::for_each with nested bind of delete?
Hi again,
i have found a decision:

1
2
3
4
typedef std::tr1::function < void(void*) > deleter;
std::tr1::shared_ptr < void > s((void*)NULL,
    std::tr1::bind(&std::for_each < void**, deleter >, p, p + 3,
        deleter(std::tr1::bind(&::operator delete, std::tr1::placeholders::_1))));


from another forum:
http://lists.boost.org/boost-users/2009/03/45772.php
Also i found that msvs2008 SP1 c++ compiler crashes in this case:


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

int _tmain(int argc, _TCHAR* argv[])
{
    void* p[] = { (void*)1, (void*)2, (void*)3 };

    std::tr1::shared_ptr < void > s((void*)NULL,
        std::tr1::bind(&std::for_each < void**, std::tr1::function < void(void*) > /*>*/, p, p + sizeof(p) / sizeof(*p),
            std::tr1::function < void(void*) >(std::tr1::bind(&::operator delete, std::tr1::placeholders::_1))));

    return 0;
}


this code compiles and works fine without comment, but with comment /*>*/ - you can see a compiler crash:)

LOG:
------ Build started: Project: test_, Configuration: Debug Win32 ------
Compiling...
test_.cpp
e:\test_\test_\test_.cpp(13) : fatal error C1001: An internal error has occurred in the compiler.
(compiler file 'msc1.cpp', line 1411)
 To work around this problem, try simplifying or changing the program near the locations listed above.
Please choose the Technical Support command on the Visual C++ 
 Help menu, or open the Technical Support help file for more information
Build log was saved at "file://e:\test_\test_\Debug\BuildLog.htm"
test_ - 1 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
now sti, you love to talk to yourself, don't ya?

now sorry for that unqualified comment but if I had to resolve that line I'd crash, too.

Can't you think of something less complicated...
@sti: Did you consider using a boost::ptr_vector<> instead of a C-style array? This would eliminate
the need for the custom deleter.

I realize the ptr_vector<> is a dynamically sizeable array vs. your fixed-length array, but there isn't
a boost::ptr_array<> template.
to jsmith:

First, the decision below does not work, because 'delete' doesn't call d-tor:

1
2
3
4
typedef std::tr1::function < void(void*) > deleter;
std::tr1::shared_ptr < void > s((void*)NULL,
    std::tr1::bind(&std::for_each < void**, deleter >, p, p + 3,
        deleter(std::tr1::bind(&::operator delete, std::tr1::placeholders::_1))));


Of course this was an ugly decision.

Second, thanks for your reply, and i wrote simple ptr_vector (i dont want to make dependencies on boost), so:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
template < typename T >
class ptr_vector 
    : public std::vector < T >
    , private utils::noncopyable
{
public:
    ptr_vector(int size) : std::vector < T >(size)
    { }

    ~ptr_vector()
    {
        std::for_each(begin(), end(), ptr_vector < T >::safe_deleter);
    }

    static void safe_deleter(T pBuf)
    {
        pBuf && delete pBuf;
    }
};
You might want to consider doing something with vector<>::erase(), as it now has the potential
to leak memory.

One other thing to consider is making a more friendly iterator. The problem now is that you have
to double dereference the iterator to get at the actual type. boost::ptr_vector<> provides an
iterator that does the pointer dereference for you.

You might also consider making your constructor explicit, and use size_t (or std::vector<>::size_type)
instead of int.

And of course inheriting from an STL container is a bit dangerous, which I'm sure you already know.


Also, resize(), and any other method that can remove elements from the vector implicitly.
Topic archived. No new replies allowed.