2

i'm working into a Visual Studio project (v120 Compiler) that uses std::thread to read from usb device aside from the GUI, and the function throws an error : "Error C2661 'std::thread::thread' : no overloaded function takes 3 arguments"

here's code:

class IOThread
{
public:
IOThread(DeviceHandler *handle) : _handle(handle)
~IOThread();

std::thread *getThread(ThreadType type);

template <typename T>
void execRead(std::list<T> *dataStack)
{
    std::thread *thread = getThread(Read);

    if (thread == NULL)
    {
        thread = new std::thread(&DeviceHandler::readFromBus, _handle, dataStack);
        _threadPool.push_back(std::make_pair(Read, thread));
    }
}

private:
DeviceHandler                                       *_handle;
std::vector<std::pair<ThreadType, std::thread *>>   _threadPool;
};

moreover, DeviceHandler is an abstraction class, which defines pure virtual readFromBus function, which prototype is the following

template <typename T>
void readFromBus(std::list<T> *dataStack) = 0;

I wish you not to have the same headache as i do while solving this mess... Regards,

stalker2106
  • 118
  • 9
  • Did you intentionaly cut off ctor body? – Glapa Oct 30 '15 at 12:06
  • What version of MSVS are you using? What is the signature of `DeviceHandler::readFromBus`? – NathanOliver Oct 30 '15 at 12:07
  • @NathanOliver He's passing `_handle`... – Brandlingo Oct 30 '15 at 12:09
  • @MatthäusBrandl Oops so he is. removed that bit. – NathanOliver Oct 30 '15 at 12:11
  • I cannot reproduce your problem. Please post a [MCVE](http://stackoverflow.com/help/mcve). – Brandlingo Oct 30 '15 at 12:13
  • 1
    Is it possible that `DeviceHandler::readFromBus` is an overloaded function? See [this answer](http://stackoverflow.com/a/14306975/1969455) – Brandlingo Oct 30 '15 at 12:18
  • Actually, i managed to get it compiling if the execRead member is not in template form, i updated the main post with the protoype of the called func, but can't get it to work if templated... the types it should expect in template is wether uint32_t or float, And yes, i intentionally put only the header file, and truncated constructor, as i tried to minimize the code but show anyway what is assigned to what – stalker2106 Oct 30 '15 at 12:27
  • Due to the template you have several overloads of `DeviceHandler::readFromBus`. This means that your problem is the same as in the question I linked. So you might want to try the same solution. – Brandlingo Oct 30 '15 at 12:36
  • The thing is, the function is not actually overloaded but templated.. will try to define pointer to templated function anyway, brb to give you the result – stalker2106 Oct 30 '15 at 12:41
  • i'm not able to define a function pointer matching readFromBus prototype, i defined it this way but i dont know the correct syntax: void (*DeviceHandler::func)(std::list *) = &DeviceHandler::readFromBus; – stalker2106 Oct 30 '15 at 12:50
  • Yes it is templated, this creates arbitrarily many methods which are only differentiated by their argument. Hence there exist arbitrarily many overloads. – Brandlingo Oct 30 '15 at 12:54
  • Btw don't use raw pointers in STL containers. Either use `std::vector>` and `emplace_back()` your new threads. Or use `unique_ptr` as in `std::vector>>`. And why don't you use a `std::map`? It seems you're doing lookups in `getThread()`. – Brandlingo Oct 30 '15 at 13:07

2 Answers2

2

As explained in the comments your situation is the same is in this question. Because the method DeviceHandler::readFromBus() is templated arbitrarily many overloads can be generated. (They share the name but have different signatures).

Because of this the compiler cannot select the correct overload, hence the error message. You will need to tell the compiler which overload to use by a cast. (as this answer explains)

The following cast should do:

thread = new std::thread(
     static_cast<void (DeviceHandler::*)(std::list<T> *)>(&DeviceHandler::readFromBus),
     _handle, dataStack);
Community
  • 1
  • 1
Brandlingo
  • 2,817
  • 1
  • 22
  • 34
  • Nice workaround ! It actually does compile, but throws syntax error onto readFromBus prototype now.. "Error C2059 syntax error : 'constant' " – stalker2106 Oct 30 '15 at 12:59
  • If the syntax were wrong it would not compile, I don't understand. I created a similar situation as yours where [the cast works](http://ideone.com/NLLomy). – Brandlingo Oct 30 '15 at 13:02
  • I guess our two environnement differs, i'm actually launching a thread to a member member function, whereas in your case, its actually a basic func that calls thread. You actually use bind also, and i'm not aware of its behaviour and the usage it implies.. i'll check reference cheat sheets. furthermore, i can't see any constant declaration on the pure prototype, do you ? – stalker2106 Oct 30 '15 at 13:05
  • Correct, I made my example minimal. If you had given a minimal example I could have reused your code. I don't get the "constant declaration on the pure prototype" part. And I still can't understand how your code compiles with syntax errors in it. Please try to explain more precisely. – Brandlingo Oct 30 '15 at 13:10
  • My example now starts threads. What it lacks is a templated pure virtual method as this is illegal in C++. I can't understand how this possibly works for you. My best guess is that your class is templated but that is not what you posted. I can't help you without the MCVE. – Brandlingo Oct 30 '15 at 13:19
  • I can try to give minimal example, but i'd rather do it with emacs+gcc because Visual Studio wants me to create project and all that... I'm hating windows environnement since i started devlopping on it ! About the constant: The readFromBus pure prototype throws the "syntax error : constant", which leads me to think that something in its declaration is interpreted as constant, but i can't tell what.. Also, the IOThread.cpp compiles, thats what i meant by "it does compile" To answer your comment, the class is not templated at all... its just not virtual because as you said its illegal in c++11 – stalker2106 Oct 30 '15 at 13:24
  • In your questin you give the code `template void readFromBus(std::list *dataStack) = 0;`. This looks templated and having a pure virtual specifier without the virtual keyword. That's actually two syntax errors in that line. Correct it and I'll see. Btw I updated the example to templated classes. And give [ideone](http://ideone.com) or [coliru](http://coliru.stacked-crooked.com/) a try, they support various compilers. – Brandlingo Oct 30 '15 at 13:33
  • Is "`readFromBus` throws" as in throws an exception? There I can't help you without code regarding this. All I can do and did is helping you with your compiler error. Feel free to start a new question for that. – Brandlingo Oct 30 '15 at 13:34
0

I tried to give a MVCE of the error, but i can't test if it compiles; but here's the actual structure of classes using your cast

thread = new std::thread(
 static_cast<void (DeviceHandler::*)(std::list<T> *)>(&DeviceHandler::readFromBus),
 _handle, dataStack);

http://ideone.com/gVh1Du

EDIT: I solved the problem, the issue was the templated pure definition, which i replaced by a function that takes in parameters an abstract struct as follows

typedef struct s_dataStack
{
  DataType type;
  std::list<void *> stack;
} t_dataStack;

and then i cast any stack element with provided type in enum "datatype". Thanks for the help given anyway, it led me to the origins of the issue.

stalker2106
  • 118
  • 9