Calling a purely template lambda callback in C++20 [duplicate] - c++

This question already has answers here:
Pass C++20 Templated Lambda to Function Then Call it
(2 answers)
Closed 9 months ago.
With C++20, we've gained templated lambdas, great!
[]<class T>(){};
Is it possible to call a lambda callback with a template parameter, but no argument to deduce it from?
For ex,
template <class Func>
void do_it(Func&& func) {
// Call lambda with template here, but don't provide extra arguments.
// func<int>(); ?
}
do_it([]<class T>(){ /* do something with T */ });

Is it possible to call a lambda callback with a template parameter,
but no argument to deduce it from?
This is probably what you want
template <class Func>
void do_it(Func&& func) {
func.template operator()<int>();
}

Related

Template member switch using enable_if and is_default_constructible [duplicate]

This question already has answers here:
Member function template selection and SFINAE
(1 answer)
SFINAE not working to conditionally compile member function template
(1 answer)
Approaches to function SFINAE in C++
(2 answers)
Closed 2 years ago.
I want to switch between to members of a templatized class based on the fact the type of the template is default constructible or not.
I think I'm not far from the solution after a lot of reading and tries around std::enable_if and std::is_default_constructible, but I'm still stuck at compile-time, here's a minimized exemple :
template<typename DataType>
class MyClass{
public:
template < typename = typename std::enable_if_t<std::is_default_constructible_v<DataType>>>
inline void createNew(unsigned int index) {
new (&this->buffer[index]) DataType(); // "placement new"
}
template < typename = typename std::enable_if_t<!std::is_default_constructible_v<DataType>>>
inline void createNew(unsigned int index) {
throw BaseException("No default constructor");
}
};
This last try results on "member function already defined or declared". I think I miss something, but I don't understand why both functions are selected for compilation even if they have the exact opposite template condition.

Function specialization with array argument [duplicate]

This question already has answers here:
C++ function template partial specialization?
(7 answers)
Closed 5 years ago.
Is it possible to specialize a function for a specific array type?
For example having a template function:
template <typename T, size_t size>
void process(T (&arr)[size])
{
// do smth
}
Could a function specialization for T=uint8_t be done in such case? Or is the only reasonable solution here to use an overload like the one below?
template <size_t size>
void process(uint8_t (&arr)[size])
{
// do smth else
}
Thanks for suggestions and comments.
It is not possible to specialize function templates partially, so you will probably have to use a separate overload.

How to use lambda as template argument with default value in C++? [duplicate]

This question already has an answer here:
Can we use a lambda-expression as the default value for a function argument?
(1 answer)
Closed 6 years ago.
I want to do a simple thing:
void DoUntil(auto predicate = [] { return false; });
Obviously this doesn't work - I have to use a template argument:
template <typename P>
void DoUntil(P predicate = [] { return false; });
But this statement doesn't work either - the Clang gives an error:
error: no matching function for call to …
note: candidate template ignored: couldn't infer template argument 'P'
If I do call the function without arguments, somehow compiler fails to deduce type from a default argument:
int main() { DoUntil(); }
I don't want to use std::function<> in any way.
Are there any other possible solutions to my problem?
Use function overloading instead of the default argument feature. Create a non-template function that takes no arguments in addition to the template function:
void DoUntil() ;
template <typename P>
void DoUntil(P predicate) ;
The no-argument version can simply invoke the template version with the lambda you want to use as the default predicate:
void DoUntil() { DoUntil([] { return false; }); }
The problem with your original approach is that you're trying to provide a default template specialization by specifying a default argument value, but without specifying a default template-type. Even without involving lambdas, the following won't work because T doesn't have a default type, even though t has a default value:
template <typename T>
void Foo(T t = 3);
What's needed is to specify a default type for T using <typename T = int>.
As noted in WhiZTiM's answer, the default type for the case involving the lambda function must be deduced using decltype. This is of course because lambdas have unique types known only to the compiler.
A lambda is an anonymous type with no default constructor (of cause, you can use its copy/move constructor if available). If you must go the lambda way, you can do:
namespace detail{ auto predicate = [] { return false; }; }
template <typename P = decltype(detail::predicate)>
void DoUntil(P pred = detail::predicate);
Rather than trying to fiddle around with lambdas. You can go the good old way:
namespace detail{
struct DefaultPredicate{ bool operator()() const { return false; } };
}
template <typename P = detail::DefaultPredicate>
void DoUntil(P predicate = P{});
Or better still as Kyle Strand answered.

Cannot Pass Variable Args to Nested Variadic Template Call [duplicate]

This question already has answers here:
Where and why do I have to put the "template" and "typename" keywords?
(8 answers)
Closed 6 years ago.
Compiler: TDM-GCC 5.1.0 (SJLJ Unwinding)
I'm having an issue passing variable number of type arguments to a static variadic template method call inside of a template function. I've tried every syntax variation, but it won't compile, so I can only assume I'm doing this wrong.
Here's the setup:
#include <iostream>
template <class T>
struct Foo
{
template <class...>
static void test()
{
std::cout << "Foo<T>::test<...>() called.";
}
};
template <class T, class... Args>
void bar()
{
Foo<T>::test<Args...>(); //error happens here
}
int main()
{
bar<int, int>();
}
This gives the compiler error: expected primary-expression before '...' token.
I thought pack expansions looked like Args..., but that doesn't seems to work here.
Any help is appreciated.
You need to tell the parser that dependant test is a template:
template <class T, class... Args>
void bar()
{
Foo<T>::template test<Args...>(); //error happens here
^^^^^^^^^
}
demo

unable to determine the template type even it is passed in [duplicate]

This question already has answers here:
Where and why do I have to put the "template" and "typename" keywords?
(8 answers)
Closed 7 years ago.
I have the following code:
template <typename T>
struct Data {
struct Embed
{
T t;
};
};
struct Functor {
template <typename T>
void foo( typename Data<T>::Embed & e) {}
};
template <typename T, typename F>
struct Caller
{
F f;
template <typename T>
void invoke() {
typename Data<T>::Embed e;
f.foo<T>(e); //compiler error pointed this line
}
};
Then I specialized the template as:
Caller<int, Functor> c;
c.invoke();
compiler error is : error: expected primary-expression before '>' in f.foo<T>(e); line. It seems compiler suddenly doesn't know what T is even it is specified in the template declaration on the function.
Take out the explicit specified T in foo.invoke(e) line will result could not deduce template parameter 'T'
How do I fix this? (I still want to keep the functionality that Caller can have generic functor and functor's function can be templated).
You are using:
template <typename T>
void invoke() {
typename Data<T>::Embed e;
f.foo<T>(e); //compiler error pointed this line
}
inside Caller even though T is one of the parameters of Caller. Remove the line
template <typename T>
and use just:
void invoke() {
typename Data<T>::Embed e;
// f.foo<T>(e); //compiler error pointed this line
f.template foo<T>(e); // Need the template keyword here.
}
However, as #Nawaz pointed out in a comment, that changes the semantics of invoke. If T in invoke was meant to be different than the T used to instantiate Caller, then it will be better to use a different name, say U.
The problem is that f is of type F which is template parameter, f.foo is a dependent name and which happens to be a function template. So you've to use template in a very weird way:
f.template foo<T>(e);
For further explantion, see these:
short explanation
long explanation
Also, I'd advise you to use U as template parameter for the function template invoke if at all it needs to be a template, else you can make it a normal function (i.e if the T of invoke is ought to be same as T of the enclosing class template).
Hope that helps.