Boost :: thread thread () takes no arguments

The IDE complains that the stream does not contain the number of parameters that I am passing. This is because there are too many of them, I believe ...

I had the same problem when I was using the standard library for threads, but when dealing with compatibility issues, I need to use Boost :: threads. HERE is a link to my previous question where someone explained that the problem was caused by belief patterns.

This was indeed a problem, however, after switching to raising threads, this error comes back and changing veriadic max does not fix it.

this is my flow declaration

boost::thread db(writeToDB, coordString, time, std::to_string(id), imageName, azimuth, att_pitch, att_roll, yaw, cam_pitch, cam_roll);

EDIT:

This is how I tried the bind function:

boost::thread db(boost::bind(::writeToDB, coordString, time, std::to_string(id), imageName, azimuth, att_pitch, att_roll, yaw, cam_pitch, cam_roll));

And the current IDE is Visual Studio 2013, however it should be compatible with Visual Studio 2008

Also here comes the real error I'm getting:

Mistake:

Error 6 error C2661: 'boost::thread::thread' : no overloaded function takes 11 arguments c:\users\hewittjc\desktop\final project\project1\clientexample.cpp 174 1 Project1

+3


source to share


3 answers


Boost.Thread (which internally uses Boost.Bind for binding arguments) only supports a certain fixed number of arguments ( doc ):

Stream constructor with arguments

template <class F,class A1,class A2,...>
thread(F f,A1 a1,A2 a2,...);

      

Prerequisites:

F

and each An

must be copied or moved.

Effects:

As if thread(boost::bind(f,a1,a2,...))

. Consequently, F

each one is An

copied to internal memory to access the new thread.

Postconditions:

*this

refers to the newly created thread of execution.

Throws:

boost::thread_resource_error

if an error occurred.

Error conditions:

resource_unavailable_try_again

: The system did not have enough resources to create another thread, or the limit on the number of threads in the process would exceed the system limit.

Note:

In addition to the functions F

you can specify up to nine additional arguments a1

to a9

.

Obviously, this means that passing 11 arguments (like you) should result in the error you see: "no overloaded function takes 11 arguments".



Unfortunately, there is no easy way to expand the limit. Possible solutions:

  • reduces the total number of arguments (you only exceeded one limit)

  • using another library to bind arguments like Boost.Phoenix

  • wrapping arguments in a class type variable (or at least some of them)

  • moving to std::thread

    a C ++ 11 compiler that fully supports variadic templates.

+2


source


From Boost.Thread Documentation :

Note:

In addition to f, you can specify up to nine additional arguments a1 through a9.

Boost.Bind has the same limitation. You can try std::tr1::bind

which MSVC 2008 has, but I suspect it will be similar - you really need variadic templates to get it bind

right, and MSVC 2008 does not. I think the only guys really crazy to see this with preprocessor metaprogramming were the Boost.Spirit people who turned it into Boost.Phoenix. There you can specify the upper bound of the preprocessor like this:

// Set this before headers are included.
// ...best set it projectwide. I don't know if funny stuff happens if Phoenix is
// used with different limits in different translation units.
//
// Also, please read the stuff below.
//
#define BOOST_PROTO_MAX_ARITY 20
#define BOOST_PROTO_MAX_LOGICAL_ARITY 20

#include <boost/phoenix/bind.hpp>
#include <boost/thread.hpp>

#include <iostream>

void foo(int x0, int x1, int x2, int x3, int x4,
         int x5, int x6, int x7, int x8, int x9,
         int x10)
{
  std::cout << x0 << x1 << x2 << x3 << x4
            << x5 << x6 << x7 << x8 << x9
            << x10 << "\n";
}

int main() {
  boost::thread th(boost::phoenix::bind(&foo, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
  th.join();
}

      



Now this function is pretty crude. I feel like the preprocessor macros controlling this was seen as an afterthought. The Boost.Phoenix docs say that you should be able to control this through BOOST_PHOENIX_LIMIT

, and that was true once, but during the creation of the Boost.Proto framework, it seems to have changed and that the docs have not been updated. It is also rough around the edges in other ways. For example, it only works for me with a value of 20 (and I suspect 30, 40, etc. if you are really patient) - everything from 11 to 19 gives huge compiler errors and it takes a compilation age because that it suddenly has 1048576 function overloading functions to handle.

So it works (for me, as of Boost 1.55.0), but it really isn't much to rely on. Instead, I suggest you concatenate your arguments together in structs so that you have less than 10 arguments to go to writeDB

, or you write your own functor (with blackjack and ... nevermind) like

// "..." to mean the rest of the arguments
class writeDBFunctor {
public:
  writeDBFunctor(std::string coordString, ...) : coordString(cordString), ... { }

  void operator()() {
    writeDB(coordString, ...);
  }

private:
  std::string coordString;
  // ...and the other arguments saved here
}

      

and give it boost::thread

.

0


source


Well, you just need to create a temporary "box of things" if you want to use the boost stream. Simple example: I want to increase :: stream after ...

/// d2dclass
static void draw_tree(ID2D1RenderTarget* d2rt,
                      ID2D1Brush*        brush,
                      float X, float Y, float len,
                      int level,
                      float angle = -DirectX::XM_PIDIV2,
                      float dispersion = DirectX::XM_PIDIV2,
                      int split = 2, float shrink = 0.5f,
                      float sw = 1.0f,
                      ID2D1StrokeStyle* ss = NULL,
                      HANDLE interrupt = NULL);

      

Its a simple recursive tree drawing function D2D1.

Define the holder of the parameter data.

struct dth_para {
    ID2D1RenderTarget* _d2rt;
    ID2D1Brush*      _brush;
    float _X;
    float _Y;
    float _len;
    int _level;
    float _angle;
    float _dispersion;
    int _split;
    float _shrink;
    float _sw;
    ID2D1StrokeStyle* _ss;
    HANDLE _interrupt;
};

      

Define a simple version of calling a thread with boost :: thread & (link) use pattern. (you may want to do several at the same time) and the impl. In fact, this part is not sure of the need. Each thread creates a separate work area, but it can't hurt. Declare a static variable in the first function so that it doesn't disappear from the stack.

/// class d2dclass

template<size_t num_tree>
static void draw_tree_thread(boost::thread& tth,
                             ID2D1RenderTarget* d2rt,
                             ID2D1Brush*         brush,
                             float X, float Y, float len,
                             int level,
                             float angle = -DirectX::XM_PIDIV2,
                             float dispersion = DirectX::XM_PIDIV2,
                             int split = 2, float shrink = 0.5f,
                             float sw = 1.0f,
                             ID2D1StrokeStyle* ss = NULL,
                             HANDLE interrupt = NULL) {
    static dth_para tree_para;
    tree_para._d2rt = d2rt;
    tree_para._brush = brush;
    tree_para._X = X;
    tree_para._Y = Y;
    tree_para._len = len;
    tree_para._level = level;
    tree_para._angle = angle;
    tree_para._dispersion = dispersion;
    tree_para._split = split;
    tree_para._shrink = shrink;
    tree_para._sw = sw;
    tree_para._ss = ss;
    tree_para._interrupt = interrupt;
    tth = boost::thread(boost::bind(&draw_tree_thread_mpl, boost::ref(tree_para)));
}

static void draw_tree_thread_mpl(dth_para& params) {
    draw_tree(params._d2rt,
              params._brush,
              params._X,
              params._Y,
              params._len,
              params._level,
              params._angle,
              params._dispersion,
              params._split,
              params._shrink,
              params._sw,
              params._ss,
              params._interrupt);
}

      

And just call the appropriate function.

boost::thread sth;
d2dclass::draw_tree_thread<0>(sth,
                              d3d->getd2rendertarget(),
                              pRadialGradientBrush0,
                              d3d->get_ww() / 2,
                              d3d->get_wh() - TREE_LEN,
                              TREE_LEN,
                              LEVELS,
                              -DirectX::XM_PIDIV2,
                              DISPERSION,
                              2,
                              OPA_SHRINK,
                              -6.0f,
                              NULL,
                              interrupt);

      

0


source







All Articles