std::thread calling template function out of template function - c++

I am trying to create threads out of a template function giving the thread another template function.
I have appended an expample of the situation that gives the same errors. Giving the thread a function that is not templated (ie here one with int and one with float) does not result in an error.
However since I plan to use this function with many different types I don't want to specify the template types. Also I have tried several specifyings of the template type (eg std::thread<T> or std::thread(function<T>) without any success.
Question: How can I call a template function with a std:thread out of a template function?
The following is a minimum compiling example of the situation, in reality the templates are own classes:
#include <thread>
#include <string>
#include <iostream>
template<class T>
void print(T* value, std::string text)
{
std::cout << "value: " << *value << std::endl;
std::cout << text << std::endl;
}
template<class T>
void threadPool(T* value)
{
std::string text = "this is a text with " + std::to_string(*value);
std::thread(&print, value, text);
}
int main(void)
{
unsigned int a = 1;
float b = 2.5;
threadPool<unsigned int>(&a);
threadPool<float>(&b);
}
compiling this example with g++ or icc with:
icc -Wall -g3 -std=c++11 -O0 -pthread
gives the folowing error messages (icc):
test.cpp(17): error: no instance of constructor "std::thread::thread" matches the argument list
argument types are: (<unknown-type>, unsigned int *, std::string)
std::thread(&print, value, text);
^
detected during instantiation of "void threadPool(T *) [with T=unsigned int]" at line 24
test.cpp(17): error: no instance of constructor "std::thread::thread" matches the argument list
argument types are: (<unknown-type>, float *, std::string)
std::thread(&print, value, text);
^
detected during instantiation of "void threadPool(T *) [with T=float]" at line 25
compilation aborted for test.cpp (code 2)
Thank you very much in advance

That's because just print is not a complete type.
I haven't tried it, but doing e.g. &print<T> should work.
Unrelated, but there's no need to pass pointers to your threadPool function. Passing a (possible constant) reference would probably be better.

Use this:
template<class T>
void threadPool(T* value)
{
std::string text = "this is a text with " + std::to_string(*value);
std::thread(&print<T>, value, text);
}

Try
std::thread([value,text]() { print(value, text); });

Related

Why does the type deduction for std::endl fails?

In the following code:
#include <iostream>
auto& print = std::cout; // Type deduction for std::cout works
auto& end = std::endl; // But the std::endl is exception here
int main(void) {
print << "Hello" << end;
return 0;
}
The type deduction for std::cout takes place properly, but why doesn't it works for std::endl?
Note: Removing the reference to operator (ampersand) doesn't works either.
The VS Code says:
And the compiler generates the following:
$ g++ -Wall -O3 -std=c++14 -o main main.cpp; ./main
main.cpp:4:18: error: unable to deduce 'auto&' from 'std::endl'
4 | auto& end = std::endl; // But the std::endl is exception here
| ^~~~
main.cpp:4:18: note: couldn't deduce template parameter 'auto'
std::cout is an object of a concrete type std::ostream (aka the std::basic_ostream<char> specialization), so auto can deduce its type.
std::endl is not an object at all, it is a template function (specifically, a stream manipulator taking a templated std::basic_ostream object as a parameter):
template< class CharT, class Traits >
std::basic_ostream<CharT, Traits>& endl( std::basic_ostream<CharT, Traits>& os );
Being a template allows std::endl to work with output streams of different character types (char, wchar_t, etc), ie std::cout vs std::wcout, etc.
But, you are not providing any values for the template parameters to tell the compiler which specialization of std::endl you want to use, so auto can't deduce a concrete type for it, hence the error.
You would have to do something like this instead:
auto& end = std::endl<char, std::char_traits<char>>;
Live Demo

Trouble definining hash function for custom type in unordered_multimap on MacOS

So I want to use a custom type (here, SWrapper) as the key type for an unordered_multimap. I've defined a hash class, derived from the standard hashing function for strings, and included the hashing class in the type of the multimap. Some code that reproduces the error is displayed below. This compiles on Arch Linux with both g++ and clang++, but on MacOS with clang++, I get errors:
#include <unordered_map>
#include <functional>
#include <string>
class SWrapper {
public:
SWrapper() {
(*this).name = "";
}
SWrapper(std::string name) {
(*this).name = name;
}
bool operator==(SWrapper const& other) {
return (*this).name == other.name;
}
std::string name;
};
class SWrapperHasher {
size_t operator()(SWrapper const& sw) const {
return std::hash<std::string>()(sw.name);
}
};
int main(int argc, char* argv[]) {
auto mm = std::unordered_multimap<SWrapper, int, SWrapperHasher>();
return 0;
}
Running g++ -std=c++11 -Wall -Wpedantic -Wextra hash_map_test.cpp -o hash_map_test on Arch Linux (or clang++) compiles the code with no errors. However, on MacOS, using the same command, I get the following error message:
In file included from hash_map_test.cpp:1:
In file included from /Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/unordered_map:408:
/Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/__hash_table:868:5: error:
static_assert failed due to requirement 'integral_constant<bool, false>::value' "the
specified hash does not meet the Hash requirements"
static_assert(__check_hash_requirements<_Key, _Hash>::value,
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/__hash_table:883:1: note: in
instantiation of template class
'std::__1::__enforce_unordered_container_requirements<SWrapper, SWrapperHasher,
std::__1::equal_to<SWrapper> >' requested here
typename __enforce_unordered_container_requirements<_Key, _Hash, _Equal>::type
^
/Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/unordered_map:1682:26: note: while
substituting explicitly-specified template arguments into function template
'__diagnose_unordered_container_requirements'
static_assert(sizeof(__diagnose_unordered_container_requirements<_Key, _Hash, _Pred>(...
^
hash_map_test.cpp:29:15: note: in instantiation of template class
'std::__1::unordered_multimap<SWrapper, int, SWrapperHasher, std::__1::equal_to<SWrapper>,
std::__1::allocator<std::__1::pair<const SWrapper, int> > >' requested here
auto mm = std::unordered_multimap<SWrapper, int, SWrapperHasher>();
^
1 error generated.
I've tried interpreting the error message, but I'm really at a loss of what to make of it. If anyone has any suggestions as to what's going on here, and how I can work around this on MacOS, it'd be greatly appreciated!
The compiler's complaint unfortunately does not say which requirement was not met. In this case, the problem comes from SWrapperHasher::operator() being private. Marking that public (changing class to struct does this implicitly) makes the unordered map legal.

Array bound set by a function of a generic

I want to set the array length to be the minimum of a constant and a generic like this:
template <int foo> struct Bar{
void my_func( int const (&my_array)[std::min(5, foo)] ) { /*...*/ }
};
This code compiles with clang++ but not g++ and I need my code to work with both. The error g++ gives is: error: array bound is not an integer constant before ']' token. How I can set the length of this array to be the minimum of foo and 5?
When I use clang++ I run into the problem that I can't get anything to bind to my_array. I want to run something like:
int main() {
static const int var[5] = {0,1,2,3,4};
Bar<5> bar;
bar.my_func(var);
}
But when I try to compile this code in clang++ I get: error: reference to type 'const int [*]' could not bind to an lvalue of type 'const int [5]'.
If I get rid of the std::min() stuff and replace it with foo the code compiles and runs fine.
Notes:
To get this code to compile you'll need to #include <algorithm> or similar to access std::min.
I don't think that this being part of a template should matter but when I try similar things with non-template function such as:
const int const_five = 5;
void new_func( int const (&my_array)[std::min(5,const_five)] ) { /*...*/ }
g++ says: error: variable or field 'new_func' declared void and clang++ says candidate function not viable: no known conversion from 'const int [5]' to 'const int [std::min(5, const_five)]' for 1st argument which both look like similar problems.
For int const (&my_array)[std::min(5, foo)] to compile, you need a version of std::min which is constexpr. It is since C++14.
Check the default value for -std of gcc and clang you use (its version-dependant). Ultimately, compile with -std=c++14.
Provided by StoryTeller, a nice working MCVE.
Keep it simple:
[foo < 5 ? foo : 5]

boost function bind compiled with a conversion error

I have the following code
#include <boost/function.hpp>
#include <boost/bind.hpp>
class Foo {
public:
int getIfoo();
};
int Foo::getIfoo() {
return 5;
}
int main () {
boost::function<int (Foo)> getIntFoo;
getIntFoo = boost::bind( &Foo::getIfoo, _1 );
return 0;
}
When I compile with the following command g++ TestBoostBind.cpp I've got the following error
/includes/boost_1_60_0/boost/bind/mem_fn_template.hpp:35:36: error: invalid conversion from ‘const Foo*’ to ‘Foo*’ [-fpermissive]
BOOST_MEM_FN_RETURN (u.*f_)();
~~~~~~~^~
I'm confused about the source of the error whether it's originally from my code or the boost library. Does anyone know what the error means and how to fix it? I use g++ (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0 and boost.1.60
When binding to a member function, the first argument needs to be a pointer or a reference to the object to call the function on. It specifically can't be a value (an actual object instance). The boost::bind function have special cases for these two alternatives to generate the correct objects. It does not have any special case for passing by value.
Therefore you need to define getIntFoo as a function taking a pointer to Foo:
boost::function<int (Foo*)> getIntFoo;
Or a reference:
boost::function<int (Foo&)> getIntFoo;
You could try to use std::mem_fn to achieve the same goal:
Foo f;
std::function<int(Foo &)> getIntFoo = std::mem_fn(&Foo::getIfoo);
int ret = getIntFoo(f);
or if you need pointer argument, std::function could resolve this for you:
Foo f;
std::function<int(Foo *)> getIntFoo = std::mem_fn(&Foo::getIfoo);
int ret = getIntFoo(&f);
boost have its own alternative

Is it possible to expand a parameter pack with a lambda function?

I think my question is a corner case, of how far you can go with parameter pack expansion and it's a little hard to explain, what I want. The idea is easiest to express with a little code, so lets have a look at the following lines:
// <main.cpp>
#include <tuple>
#include <iostream>
// this function is supposed to return a std::tuple of function objects
// for each template argument type, there should be one such function object,
// that takes a value of this type and returns its half.
template <class... arg_t>
auto make_divide_by_two_lambda_tuple() {
return std::make_tuple(
[](const arg_t& elem) -> arg_t
{
return elem/2;
}...
);
}
int main()
{
// lets initialise a tuple with our function
auto value = make_divide_by_two_lambda_tuple<int, float>();
/*
* If everything workes as planned, the tuple has this structure
* value<0> := [](const int&){ ... }
* value<1> := [](const float&){ ... }
*/
// and we are able to use our functions in the expected way
std::cout << "5/2 (int version) = " << std::get<0>(value)(5) << std::endl;
std::cout << "5/2 (float version) = " << std::get<1>(value)(5) << std::endl;
return 0;
}
For clang(4.0.1), this example compiles and run as I expect it to do:
$ clang++ -std=c++14 ../main.cpp
$ ./a.out
5/2 (int version) = 2
5/2 (float version) = 2.5
For g++(7.1.1), this example does fail to compile:
$ g++ -std=c++14 ../main.cpp
../main.cpp: In function ‘auto make_divide_by_two_lambda_tuple()’:
../main.cpp:7:28: error: parameter packs not expanded with ‘...’:
[](const arg_t& elem) -> arg_t
^~~~~
../main.cpp:7:28: note: ‘arg_t’
../main.cpp:7:28: error: parameter packs not expanded with ‘...’:
../main.cpp:7:28: note: ‘arg_t’
../main.cpp:10:4: error: expansion pattern ‘<lambda>’ contains no argument packs
}...
^~~
../main.cpp: In function ‘int main()’:
../main.cpp:15:10: error: ‘void value’ has incomplete type
auto value = make_divide_by_two_lambda_tuple<int, float>();
So it seems, that gcc is willing to use a parameter pack inside the argument list of a lambda expression. But using the whole lambda is stretching it too far for gcc to accept.
Is this use of lambda expressions undefined behaviour, or is one compiler (hopefully gcc) wrong?
PS.: I also checked the docs, but it only explains, where you can use parameter pack expansion, and not what statments you can expand.