I know, that there exists the possibility for automatic type deduction of function templates, given a particular function parameter, but does there also exist such a method for non type template parameters?
Example:
#include <iostream>
template<typename T, T val>
void func_a(void) {
std::cout << val << std::endl;
}
template<typename T>
void func_b(T val) {
std::cout << val << std::endl;
}
int main(void) {
func_a<uint32_t, 42u>();
//func_a<42u>(); //This line doesn't work
func_b(42u);
return 0;
}
So I don't want to give each time the template argument type uint32_t every time, when I call func_a(). Does there such a method exist in C++17 or below?
I am using g++ v.7.3 and c++17.
In C++17, you can use auto:
template<auto val>
void func_a(void) {
std::cout << val << std::endl;
}
int main(void) {
func_a<42u>();
return 0;
}
Given a +1 for the C++17 solution, a better-than-nothing C++11/C++14 solution can be the use of a macro to activate decltype() over the argument.
By example, with the macro
#define func_a_macro(val) func_a<decltype(val), val>
or better, as suggested by liliscent, to avoid problems with references
#define func_a_macro(val) \
func_a<std::remove_reference<decltype(val)>::type, val>
you can call
func_a_macro(42u)();
p.s.: I know... I know... macros are distilled evil... but sometime are useful.
C++14 solution with no macros:
template<int N> auto Int = std::integral_constant<int, N>{};
template<class T, T n>
constexpr auto foo(std::integral_constant<T, n> x)
{
std::cout << x.value << std::endl;
}
int main()
{
foo(Int<6>);
}
c++11:
template<int N> using Int = std::integral_constant<int, N>;
template<class T, T n>
constexpr void foo(std::integral_constant<T, n> x)
{
std::cout << x.value << std::endl;
}
int main()
{
foo(Int<6>());
}
Related
I'm attempting to write a function that forces constexpr evaluation via. a template. I wrote this, but it works only for int (beware, will give recursion depth errors with GCC):
#include <iostream>
template<int val>
constexpr int force_constexpr() { return val; }
constexpr int triangle(int n)
{
return n ? n + triangle(n - 1) : 0;
}
int main(void)
{
std::cout << force_constexpr<triangle(0x200)>() << '\n';
}
Note that this is for demonstration purposes only; I know that the triangle number can be calculated with (n+1)*n/2.
Then I attempted to write a generic function, however, that doesn't work as well. This is a plain error (not surprising, as it uses T before T is defined):
template<T val, typename T = decltype(val)>
constexpr T force_constexpr() { return val; }
as is this (which obviously won't work; it's a nested template):
template<typename T>
template<T val>
constexpr T force_constexpr() { return val; }
and this requires the type of the argument to be passed:
template<typename T, T val>
constexpr T force_constexpr() { return val; }
How can I do this without passing the type as a parameter to the template? Or, in other words, how can I deduce a template parameter type?
I'm looking for a C++11 solution but solutions for other standards are welcome.
You're looking for auto template parameters, in C++17:
#include <iostream>
template<auto T>
auto *singleton()
{
static const decltype(T) solo{T};
return &solo;
}
int main()
{
const int *p=singleton<42>();
std::cout << "The meaning of life: " << *p << std::endl;
return 0;
}
Specify the template parameter as auto, and use decltype to deduce its type.
I do not believe that this is possible before C++17, since this is precisely the use case for which auto template parameters were added to the standard. Couldn't do this, conceptually, before then.
C++17 introduces auto as non type template parameter:
template <auto val>
constexpr auto force_constexpr() { return val; }
Before, you have indeed blocked with
template<typename T, T val>
constexpr T force_constexpr() { return val; }
You can introduce MACRO to simplify usage:
#define AUTO(v) decltype(v), (v)
And then
std::cout << force_constexpr<AUTO(triangle(0x200))>() << '\n';
Is this the only way to evaluate a parameter pack without using folding (since it requires the use of operators)?
#include <iostream>
template<int ...Is, typename Function>
void eval(Function&& f)
{
// (f(Is)...);
auto op = [&f](int i){f(i); return 0;};
auto doNothing = [](auto...){};
doNothing(op(Is)...);
}
int main()
{
eval<0,1,2>([](int x){std::cout << x << "\n";});
}
Essentially I want to do (f(Is)...), but for some reason, this is disallowed in C++. Is there a more elegant way this can be achieved than by using the workaround presented above?
There is a simpler solution:
#include <iostream>
template<int ...Is, typename Function>
void eval(Function&& f)
{
(f(Is),...);
}
int main()
{
eval<0,1,2>([](int x){std::cout << x << "\n";});
}
Is it possible to write something like this?
[](std::index_sequence<std::size_t ...I> s) {
};
Or this?
[]<std::size_t ...I>(std::index_sequence<I...> s) {
}
How is the syntax for this in C++14 or C++17? Or is it not possible at all? Basically, I just want to have the I as a template parameter pack, and the lambda just serves as a way to do that. Alternatively, is there a syntax to achieve the following?
std::index_sequence<std::size_t ...I> x = std::make_index_sequence<10>{};
// I now is a local template parameter pack
GCC provides the latter syntax as an extension, but it's not standard:
template <typename... Ts>
void foo(const std::tuple<Ts...>& t) {
auto l = [&t]<std::size_t ...I>(std::index_sequence<I...> s) {
std::initializer_list<int>{ (std::cout << std::get<I>(t), 0)... };
};
l(std::index_sequence_for<Ts...>{});
}
Live Demo
Not exactly the same, but maybe you can push the sequence with an helper function as it follows:
#include <functional>
#include <cstddef>
#include <iostream>
auto lambda = [](auto... I){
int arr[] = { (std::cout << I << std::endl, 0)... };
(void)arr;
};
template<std::size_t... I>
constexpr auto f(std::index_sequence<I...>) {
return lambda(I...);
}
int main() {
f(std::make_index_sequence<3>());
}
This question already has an answer here:
Get function arity from template parameter
(1 answer)
Closed 6 years ago.
I'm wondering if there is a way in C++11 to get the number of arguments of a function?
For example for the function foo I want argCount to be 3.
void foo(int a, int b, int c) {}
int main() {
size_t argCount = MAGIC(foo);
}
You can get that information by using a variadic function template.
#include <iostream>
template <typename R, typename ... Types> constexpr size_t getArgumentCount( R(*f)(Types ...))
{
return sizeof...(Types);
}
//----------------------------------
// Test it out with a few functions.
//----------------------------------
void foo(int a, int b, int c)
{
}
int bar()
{
return 0;
}
int baz(double)
{
return 0;
}
int main()
{
std::cout << getArgumentCount(foo) << std::endl;
std::cout << getArgumentCount(bar) << std::endl;
std::cout << getArgumentCount(baz) << std::endl;
return 0;
}
Output:
3
0
1
See it working at http://ideone.com/oqF8E8.
Update
Barry suggested use of:
template <typename R, typename ... Types>
constexpr std::integral_constant<unsigned, sizeof ...(Types)> getArgumentCount( R(*f)(Types ...))
{
return std::integral_constant<unsigned, sizeof ...(Types)>{};
}
With this, you can get the number of argument by using:
// Guaranteed to be evaluated at compile time
size_t count = decltype(getArgumentCount(foo))::value;
or
// Most likely evaluated at compile time
size_t count = getArgumentCount(foo).value;
Yes, it can be easily done:
#include <cstddef>
#include <iostream>
template <class R, class... ARGS>
struct function_ripper {
static constexpr size_t n_args = sizeof...(ARGS);
};
template <class R, class... ARGS>
auto constexpr make_ripper(R (ARGS...) ) {
return function_ripper<R, ARGS...>();
}
void foo(int, double, const char*);
void check_args() {
constexpr size_t foo_args = decltype(make_ripper(foo))::n_args;
std::cout << "Foo has " << foo_args << " arguments.\n";
}
This doesn't really make sense for several reasons.
For starters, what would this really be good for? You might be looking for some sort of reflection, but that doesn't (yet) exist in C++.
The main reason this doesn't make sense, however, is overload sets:
void f(int);
void f(int, int);
std::cout << MAGIC(f); // what should this print??
I have a function template like this:
template <class ...A>
do_something()
{
// i'd like to do something to each A::var, where var has static storage
}
I can't use Boost.MPL. Can you please show how to do this without recursion?
EDIT: These days (c++17), I'd do it like this:
template <class ...A>
do_something()
{
((std::cout << A::var << std::endl), ...);
};
What Xeo said. To create a context for pack expansion I used the argument list of a function that does nothing (dummy):
#include <iostream>
#include <initializer_list>
template<class...A>
void dummy(A&&...)
{
}
template <class ...A>
void do_something()
{
dummy( (A::var = 1)... ); // set each var to 1
// alternatively, we can use a lambda:
[](...){ }((A::var = 1)...);
// or std::initializer list, with guaranteed left-to-right
// order of evaluation and associated side effects
auto list = {(A::var = 1)...};
}
struct S1 { static int var; }; int S1::var = 0;
struct S2 { static int var; }; int S2::var = 0;
struct S3 { static int var; }; int S3::var = 0;
int main()
{
do_something<S1,S2,S3>();
std::cout << S1::var << S2::var << S3::var;
}
This program prints 111.
As an example, suppose you want to display each A::var. I see three ways to acomplish this as the code below illustrates.
Regarding option 2, notice that the order in which the elements are processed is not specified by the standard.
#include <iostream>
#include <initializer_list>
template <int i>
struct Int {
static const int var = i;
};
template <typename T>
void do_something(std::initializer_list<T> list) {
for (auto i : list)
std::cout << i << std::endl;
}
template <class... A>
void expand(A&&...) {
}
template <class... A>
void do_something() {
// 1st option:
do_something({ A::var... });
// 2nd option:
expand((std::cout << A::var << std::endl)...);
// 3rd option:
{
int x[] = { (std::cout << A::var << std::endl, 0)... };
(void) x;
}
}
int main() {
do_something<Int<1>, Int<2>, Int<3>>();
}
The answers above work -- here I explore a bit more on using a lambda for complex use cases.
Lambda 101:
[ capture ]( params ){ code }( args to call "in-place" );
If you want to expand a lambda with a variadic template, it won't work as mentioned above when the parameters is of a non-trivial type:
error: cannot pass object of non-trivial type 'Foo' through variadic method; call will abort at runtime.
The way to go is to move the code from the lambda's args to code:
template <class ...A>
do_something() {
Foo foo;
[&](auto&& ...var){
(foo.DoSomething(var), ...);
}(A::var...);
}