There is a function that uses one of two classes of descendants and is called via std::thread(MyFunc, std::ref(SpecifiedClassType)).detach() ;
The parent class does not have some descendant methods; therefore, it is not an option to declare the objects of the descendants as a parent type.

Is it possible to somehow specify which classes can be a variable in this function, or are there no options besides template<class T> ?

Explanation:

There is a class Capture which has two children - Camera and Screen . The purpose of this system is to receive frames from the camera or screenshots of the screen - and nothing more (the network should not be there). The parent has a common for children function GrabJPG , which is called in the external function, in the stream. I want the MyFunc function that I mentioned at the beginning of the topic to look something like this:

 void StreamThread(STREAMER &cgf, <только_тип_Camera_или_Screen> &source){ // где cfg - структура с параметрами сетевой конфигурации, // а source - источник кадров - камера или экран. // ... cgf.connection->open(cgf.host, cgf.port) // ... туда-сюда настройки while (cgf.connection->active()){ // ... int size = source->GrabJPG(&buffer); if( size){ cgf.connection->transmit(buffer, size); } // ... } } 

Now I have two such identical StreamThread , differing only in one variable - the class of the camera or the screen. Not beautiful, agree? There should be a compilation error if you try to thrust into the function any other class that is not a descendant of Capture . This is what is required.

  • I propose to look at abstract methods. - Qwertiy
  • one
    Possible duplicate question: Patterns in C ++ Type restriction - Andrio Skur
  • Those. all descendants have a method, but the parent does not? Why not do what @Qwertiy says? And if only some descendants that are used in the function have a method, then it makes sense to make an intermediate class with this method ... In my opinion, so ... - Harry
  • Nothing is clear. What kind of "this function" are we talking about? About std::thread or about where it all comes from? From where and why is template<class T> ? Give a meaningful context, and not some kind of mess-mess. - AnT
  • @AnT, the template function uses some function. He wants to limit the template class to those classes that have this function. It seems everything is clear? - Qwertiy

1 answer 1

There are several approaches to solving this problem:

Explicit instantiation

+ Definitions for both variants of StreamThread will be generated automatically based on a common template code using explicit instantiation directives (in the file where these directives will be specified).

+ (C ++ 11 and higher) Implicit instantiation of the StreamThread function template for the Camera and Screen template arguments can be disabled in all translation units to which the StreamThread.h header file will be StreamThread.h .

If you try to compile the StreamThread function with the value of a template argument other than Camera or Screen , a link error (rather than a compilation) will be StreamThread .

 // StreamThread.h template <typename Source> void StreamThread(SREAMER &cgf, Source &source); extern template void StreamThread(SREAMER &cgf, Camera &source); // C++11 и выше extern template void StreamThread(SREAMER &cgf, Screen &source); // C++11 и выше // StreamThread.cpp template <typename Source> void StreamThread(SREAMER &cgf, Source &source) { // ... } template void StreamThread(SREAMER &cgf, Camera &source); template void StreamThread(SREAMER &cgf, Screen &source); 

Limiting the set of types that can be used as a template argument using SFINAE

When using this approach, compilation errors will be generated if the argument of the template function does not match the Camera or Screen .

 // StreamThread.h #include <type_traits> template <typename Source> std::enable_if_t<std::is_same_v<Source, Camera> || std::is_same_v<Source, Screen>> StreamThread(SREAMER &cgf, Source &source) { // ... } 

+ If you try to compile the StreamThread function with the value of a template argument other than Camera or Screen , you will get a compilation error (indicating that the required overload of the StreamThread function StreamThread not found).

template of the StreamThread function will be implicitly instantiated in all translation units where the StreamThread.h header file is StreamThread.h and where the call to the StreamThread function StreamThread .

Combined approach

Combines the two previous options and combines their advantages.

 // StreamThread.h #include <type_traits> template <typename Source> std::enable_if_t<std::is_same_v<Source, Camera> || std::is_same_v<Source, Screen>> StreamThread(SREAMER &cgf, Source &source); extern template void StreamThread(SREAMER &cgf, Camera &source); // C++11 и выше extern template void StreamThread(SREAMER &cgf, Screen &source); // C++11 и выше // StreamThread.cpp template <typename Source> std::enable_if_t<std::is_same_v<Source, Camera> || std::is_same_v<Source, Screen>> StreamThread(SREAMER &cgf, Source &source) { // ... } template void StreamThread(SREAMER &cgf, Camera &source); template void StreamThread(SREAMER &cgf, Screen &source); 
  • Do not tell me how to call it all in the stream? I get an error: no matching function for call to std::thread::thread(<unresolved overloaded function type>, STREAMER&, Screen&) if(!SCREEN.active){std::thread(StreamThread, SCREEN, (*screen)).detach();} - Iceman
  • one
    @Iceman First, you need to explicitly indicate which StreamThread specialization you want to use as a stream function. Secondly, the arguments of the thread function, which are passed by reference, must be wrapped in std::ref / std::cref when passed to the constructor std::thread : example . - Constructor
  • Fine! It all worked! Thanks a lot! - Iceman