This is related to my earlier post. I'd like to know why one attempted solution didn't work.
template <typename... T> /* A */
size_t num_args ();
template <>
size_t num_args <> ()
{
return 0;
}
template <typename H, typename... T> /* B */
size_t num_args ()
{
return 1 + num_args <T...> ();
}
If I try to call, say, num_args<int,float>() then the error is that the function call is ambiguous:
A with T={int,float}
B with H=int, T={float}
I don't understand how this is ambiguous -- A is a declaration and B is a definition of the function declared by A. Right?
I'm trying to make this example work and the responses to my earlier question seem to claim that it can never work.
If that's the case, what's the point of variadic free functions? What can they do?
I don't understand how this is ambiguous -- A is a declaration and B
is a definition of the function declared by A. Right?
No. A is a declaration of a function template, and B is a declaration (and definition) of another function template.
The compiler has no way to decide between the two: they both have no arguments, and the template arguments are a match for both.
The one in the middle is an explicit total specialization of the function template declared in A.
If you tried to make B another specialization of A:
template <typename H, typename... T> /* B */
size_t num_args<H, T...>()
{
return 1 + num_args <T...> ();
}
... you'd end up with a partial specialization of a function template, which is not allowed.
You can do this with the usual trick of using a class template with partial specializations and a function template that calls into the class template:
template <typename... T>
class Num_Args;
template <>
struct Num_Args <>
{
static constexpr size_t calculate() {
return 0;
}
};
template <typename H, typename... T>
struct Num_Args <H, T...>
{
static constexpr size_t calculate() {
return 1 + Num_Args<T...>::calculate();
}
};
template <typename... T> /* B */
constexpr size_t num_args ()
{
return Num_Args<T...>::calculate();
}
Apropos the usefulness/uselessness of free variadic function templates: the usual use case for these is to have a variadic function parameter list, in which case a regular overload for the empty case will do just fine:
size_t num_args()
{
return 0;
}
template <typename H, typename... T> /* B */
size_t num_args (H h, T... t)
{
return 1 + num_args(t...);
}
EDIT:
As far as I can see, the following abuse of enable_if ought to work as a solution to your original question:
#include <utility>
// Only select this overload in the empty case
template <typename... T>
typename std::enable_if<(sizeof...(T) == 0), size_t>::type
num_args()
{
return 0;
}
template <typename H, typename... T>
size_t
num_args()
{
return 1 + num_args<T...>();
}
(Edit2: Reversed the order of the overloads to make the code actually compile)
While I really like the std::enable_if<sizeof...(T) == 0, _> hack by JohannesD, I'll still drop the below hack that I don't actually remember where I learned from, which resolves the ambiguity with only free functions without having to use classes:
template <typename One>
size_t num_args() {
return 1;
}
template <typename First, typename Next, typename... Rest>
size_t num_args() {
return 1 + num_args<Next, Rest...>();
}
No partial specialization required, and it totally avoids the zero parameter case by ending the unpacking recursion at one parameter. Also, see https://stackoverflow.com/a/58295007/1525238 for an even nicer c++17 solution that uses the same idea.
The only catch is that it actually doesn't cover the zero template parameter case, which is impossible in the context of free functions AFAIK. If that is required from the consumer's perspective, a partially specialized class must be used, see R. Martinho Fernandes' answer.
As for the utility of variadic template free functions, I find them particularly useful as constexpr type-safe accumulating calculator utilities.
Related
Suppose, we have
template <int> struct Node;
It is required to get "reusable" compile-time function, which counts all Node specializations, defined exactly before every call of that function (from different points of translation unit). That is, number of specializations before point of function template instantiation. To simplify solution suppose that Node specializations are introduced sequentionally, starting from zero: 0,1,2,3...
Ok, here is C++ code:
#include <type_traits>
template <typename T> decltype(T{}) InstanceOf(int);
template <typename T> void InstanceOf(...);
template <typename K, template <int> typename T, int N = 0,
typename = decltype(InstanceOf<T<N>>(0))>
struct NCount
: NCount<K, T, N + 1> {};
template <typename K, template <int> typename T, int N>
struct NCount<K, T, N, void>
: std::integral_constant<int, N> {};
template <int> struct Node;
template <typename K = void, template <int> typename T = Node>
constexpr auto Count()
{
return NCount<K, T>::value;
}
template <> struct Node<0> {};
template <> struct Node<1> {};
int main()
{
return Count(); //expected: 2
}
template <> struct Node<2> {};
Almost any code modification results in issue for some/all compilers (gcc/clang 9+ is interesting first of all):
1. if Count() body is not fully-dependent from template typename list, gcc fails:
template <typename K = void>
constexpr auto Count()
{
return NCount<K, Node>::value; //main: 0 returned
}
"Workaround" is to move the first specialization (Node<0>) before Count() template definition:
template <> struct Node<0> {};
template <typename K = void>
constexpr auto Count()
{
return NCount<K, Node>::value; //main: 2 returned
}
FYI: if K is removed from inside body in this case, we get another result (like body pre-compiled "in the place" with knowledge about single Node specialization):
template <> struct Node<0> {};
template <typename K = void>
constexpr auto Count()
{
return NCount<void, Node>::value; //main: 1 returned
}
2. if Count() return value type is specified (it is known - int), then totally all specializations is counted by both compilers:
template <typename K = void, template <int> typename T = Node>
constexpr int Count()
{
return NCount<K, T>::value; //main: 3 returned
}
Seems, that understanding function signature, compiler just "puts the call" of Count() inside main, but body of the function template will be compiled "later", after all cpp-file content is parsed (plus Node<2> spec). So the "auto" is the way to make compiler calculate NCount exactly in POI to get desired number.
Note that K-type purpose is to provide ability to be called as many times as required from any point of code. K-type must be unique every time (with respect to all other Count<K>() calls) to get actual value.
The questions are:
is there any compiler bug (including "modification" comments);
is this solution ill-formed (where);
if yes, could you give c++ standard compliant reliable solution?
p.s. I know about standard paragraphs, which tell us that class template specialization could not be used in some point if it is not defined before. But. Note that Count() first of all gets knowledge about available specializations before doing smth (indeed, in this example - no processing). Moreover, Node class main template just can not be used if not specialized - it has no definition! So...
p.s.s. In fact, all gcc/clang 5+ and icc give desirable 2. MSVC gives 0. Other [more specific] compilers give 0 also. Checked via godbolt.org, wandbox.org.
Thanks!
Can I write a template function taking an argument T that calls a member function foo if it exists on T, and if it doesn't calls a free function foo(T) instead (and fails to compile if neither exists)?
Something like:
template<typename T>
int call_foo(T t) {
// if T::foo() exists
return t.foo();
// else return foo(t);
}
How about the reverse case: preferring a free function foo before the member function? I cannot use any features introduced after C++11.
This isn't too hard. There are many methods of checking whether an arbitrary expression is valid. You can combine this with if constexpr in C++17 or tag dispatch earlier to get the behaviour you desire.
This uses C++17, but everything can be done in prior versions:
#include <type_traits>
#include <utility>
// This is just one way to write a type trait, it's not necessarily
// the best way. You could use the Detection Idiom, for example
// (http://en.cppreference.com/w/cpp/experimental/is_detected).
template <typename T, typename = void>
struct has_member_fn
: std::false_type
{};
// std::void_t is a C++17 library feature. It can be replaced
// with your own implementation of void_t, or often by making the
// decltype expression void, whether by casting or by comma operator
// (`decltype(expr, void())`)
template <typename T>
struct has_member_fn<T,
std::void_t<decltype(std::declval<T>().foo())>>
: std::true_type
{};
template <typename T, typename = void>
struct has_free_fn
: std::false_type
{};
template <typename T>
struct has_free_fn<T,
// Be wary of ADL. You're basically asking the compiler,
// "What's the result of foo(T{}) if I were to call that
// here?" That syntax can call functions via ADL
std::void_t<decltype(foo(std::declval<T>()))>>
: std::true_type
{};
template <typename T>
int call_foo(T t) {
// if constexpr is C++17, but you can use tag dispatch to
// do the same in prior versions
if constexpr (has_member_fn<T>::value) {
return t.foo();
} else {
// you could make this an `else if constexpr (has_free_fn<T>::value)`
// and provide a better case for if neither exists
return foo(t);
}
}
Live on Godbolt
Pre C++17 you can's compile/not compile different parts of the same function with if constexpr.
So, pre C++17, you have to do, somewhere, two different functions.
An example: if you prepare a couple of helper functions
template <typename T>
auto call_foo_h (T t, int) -> decltype( t.foo() )
{ return t.foo(); }
template <typename T>
auto call_foo_h (T t, long) -> decltype( foo(t) )
{ return foo(t); }
that are SFINAE enabled only if T::foo() exist (the first one) or if a free foo() exist (the second one), you can write call_foo() as follows
template <typename T>
int call_foo (T const & t)
{ return call_foo_h(t, 0); }
//......................^ a int value
Observe the second (unused) parameter in call_foo_h(); an int in the T::foo() version, a long in the free version.
Here is the trick: calling call_foo_h with an int (0) you call preferably the int version (the T::foo()), when available, and the long version otherwise.
How about the reverse case: preferring a free function foo before the member function?
In this case write call_foo() as follows
template <typename T>
int call_foo (T const & t)
{ return call_foo_h(t, 0L); }
//......................^^ a long value
That is: call call_foo_h with a long value, giving the precedence to the free foo() version.
I want to write a function which kind of iterates over a std::tuple<...>. The iteration itself won't produce any problems regarding the tuple's template types, because '...' have the same types (like int, int, int, ...). I implemented already a working function 'Foo' with a helper struct 'Helper' using template metapgrogramming – everything is fine.
But when I want to implement an alternative version, using a constexpr function 'helper', the compiler (g++ 5.2.0) gets stuck in an infinite loop of error messages. From what I can get from these messages, the 'position' template parameter is instantiated as ridicilously big (== 4294967245) instead of (== 1). I tried to get both versions as close in syntax and nomenclature as possible.
Minimal example
#include <tuple>
// template metaprogramming version
template
<class T, std::size_t position>
struct Helper{
static int
help(T tuple) {
return std::get<position>(tuple) +
Helper<T,position - 1>::help(tuple);
}
};
// template metaprogramming version, specialized
template
<class T>
struct Helper<T,0>{
static int
help(T tuple) {
return std::get<0>(tuple);
}
};
// function version, not working
template
<class T, std::size_t position>
constexpr int
helper(T tuple) {
return
0 == position ?
std::get<position>(tuple) + helper<T,position-1>(tuple) :
std::get<0>(tuple);
}
template
<class T>
auto
Foo(T tuple) {
constexpr std::size_t dimension = std::tuple_size<T>::value;
// working version, using the helper struct
return Helper<T,dimension - 1>::help(tuple);
// wrong(?) version, using the constexpr helper function
return helper<T,dimension - 1>(tuple);
}
int main() {
std::tuple<int,int> t(1,1);
Foo(t);
return 0;
}
My questions:
Is it principally wrong to try this kind of iteration during compile
time with constexpr functions?
If not, is it a bug in the compiler
or how should a correct version look like?
I am totally aware that, due to the same types in the tuple (int,int,...), one could implement a similar version with vectors. But I think that the tuple version is conceptually better to my kind of problem and faster during runtime.
When you have a function template - all the code must be compiled out. So here:
template
<class T, std::size_t position>
constexpr int helper(T tuple) {
return
0 == position ?
std::get<position>(tuple) + helper<T,position-1>(tuple) :
std::get<0>(tuple);
}
We always compile both parts of the conditional (side-note: your conditional is backwards). So when position == 0, both the std::get<0>(tuple) part is compiled and the std::get<0>(tuple) + helper<T, -1>(tuple) part is compiled. But then to do that, we'd need to compile helper<T, -2>(tuple). And helper<T, -3>(tuple). We recursive infinitely.
Your specialization approach works because Helper<T, 0> just does std::get<0>. There is no other logic in there, so we stop. If you want to do this functionally, an easier way would be to pass the position as an argument. That is:
template <std::size_t position>
using Pos = std::integral_constant<std::size_t, position>; // to save me some typing
template <typename T>
constexpr int helper(T const& tuple, Pos<0> )
{
return std::get<0>(tuple);
}
template <typename T, std::size_t position>
constexpr int helper(T const& tuple, Pos<position> )
{
return std::get<position>(tuple) + helper(tuple, Pos<position - 1>{});
}
Here, we do the conditional via overloading - so once we get to helper(T, Pos<0> ), we successfully terminate the recursion.
In C++1z, this becomes a ton easier with fold expressions, where you can just do:
template <typename T>
constexpr int sum_tuple(T const& tuple) {
return sum_tuple(tuple, std::make_index_sequence<std::tuple_size<T>::value>{});
}
template <typename T, std::size_t... Is>
constexpr int sum_tuple(T const& tuple, std::index_sequence<Is...> )
{
return (std::get<Is>(tuple) + ... );
}
So my questions: Is it principally wrong to try this kind of iteration during compile time with constexpr functions?
Yes, it's wrong, as you've done it. It can be done, but you can't terminate the compile-time recursion with a run-time condition.
When you instantiate helper<T, N>(T) that instantiates helper<T, N-1>(T) which instantiates herlper<T, N-2>(t) and so on, with nothing to terminate the recursion.
The class template version terminates when it reaches N==0 because of the partial specialization, but you can't partially specialize a function template.
Barry's solution works by using a second overload to terminate the recursion, so that when it reaches 0 it chooses a different function and doesn't keep instantiating the same one forever.
Consider the following (invalid) code sample:
// a: base template for function with only one parameter
template<typename T>
void f(T t) { }
// b: base tempalte for function with two parameters
template<typename T1, typename T2>
void f(T1 t1, T2 t2) { }
// c: specialization of a for T = int
template<>
void f<int>(int i) { }
// d: specialization for b with T1 = int - INVALID
template<typename T2>
void f<int, T2>(int i, T2 t2) { }
int main() {
f(true); // should call a
f(true, false); // should call b
f(1); // should call c
f(1, false); // should call d
}
I've read this walk-through on why, in general, partial function template specializations won't work, and I think I understand the basic reasoning: there are cases where function template specializations and overloading would make certain calls ambiguous (there are good examples in the article).
However, is there a reason why this specific example wouldn't work, other than "the standard says it shouldn't"? Does anything change if I can guarantee (e.g. with a static_assert) that the base template is never instantiated? Is there any other way to achieve the same effect?
What I actually want to achieve is to create an extendable factory method
template<typename T>
T create();
which also has a few overloads taking input parameters, e.g.
template<typename T, typename TIn>
T create(TIn in);
template<typename T, typename TIn1, typename TIn2>
T create(TIn1 in1, TIn2 in2);
In order to ensure that all necessary factory methods are present, I use static_assert in the function base templates, so that a compiler error is generated if the create method is called with template arguments for which no specialization has been provided.
I want these to be function templates rather than class templates because there will be quite a lot of them, and they will all use input from the same struct hierarchy, so instantiating 10 factories instead of one comes with some overhead that I'd like to avoid (not considering the fact that the code gets much easier to understand this way, if I can just get it to work...).
Is there a way to get around the problem outlined in the first half of this post, in order to achieve what I've tried to get at with the second half?
In response to iavr:
I could do this with plain overloading, which would (given the templates above) give something like
template<typename TIn2>
A create(bool, TIn2);
template<typename TIn2>
A create(int, TIn2);
if I need two different partial specializations with T = A, TIn1 specified and TIn2 still unspecified. This is a problem, since I have some cases (which are really text-book cases for meta-programming and templates) where I know that, for example, one of the arguments will be a std::string, and the other will be of some type that has a property fields and a property grids, which are of types std::vector<field> and std::vector<grid> respectively. I don't know all the types that will ever be supplied as the second argument - I know for sure that there will be more of them than the ones I currently have implemented - but the implementation of the method will be exactly the same.
While writing up this update, I think I've figured out a way to redesign the implementations so that there is no need for the partial specialization - basically, I do the following to cover the case outlined above:
template<>
A create<A, std::vector<field>, std::vector<grid>>(std::vector<field> fs, std::vector<grid> gs);
and then I have to change the calling signature slightly, but that's OK.
I share your concerns that maybe in this particular case there would be no problem having function template partial specializations, but then again, that's the way it is, so what would be your problem using plain overloading?
// a: base template for function with only one parameter
template<typename T>
void f(T t) { }
// b: base template for function with two parameters
template<typename T1, typename T2>
void f(T1 t1, T2 t2) { }
// c: specialization of a for T = int
void f(int i) { }
// d: specialization for b with T1 = int
template<typename T2>
void f(int i, T2 t2) { }
This also takes less typing and I get this is why you don't want to use function objects (which would have partial specialization).
Here is a simple workaround using a class template specialization:
template <typename, typename...>
struct Creator;
template <typename T, typename TIn>
struct Creator<T, TIn>
{
T call(TIn in)
{
// ...
}
};
template<typename T, typename TIn1, typename TIn2>
struct Creator<T, TIn1, TIn2>
{
T call(TIn1 in1, TIn2 in2)
{
// ...
}
};
template <typename R, typename... Arguments>
R Create(Arguments&&... arguments)
{
return Creator<R, Arguments...>::call(std::forward<Arguments>(arguments)...);
}
If you don't want overloading, and want to be able to specialize from a separate file, then I think you should base it on the solution on the link from your question. It involves making a static method on a class that you specialize. From my reading of the question, you're only interested in specializing on the T, not on the number of arguments, which you intend to forward. In C++11, you can do the following:
#include <iostream>
#include <utility>
using namespace std;
template<typename T>
struct factory_impl;
// Left unspecified for now (which causes compliation failure if
// not later specialized
template<typename T, typename... Args>
T create(Args&&... args)
{
return factory_impl<T>::create(std::forward<Args>(args)...);
}
// Note, this can be specified in a header in another translation
// unit. The only requirement is that the specialization
// be defined prior to calling create with the correct value
// of T
template<>
struct factory_impl<int>
{
// int can be constructed with 0 arguments or 1 argument
static int create(int src = 0)
{
return src;
}
};
int main(int argc, char** argv)
{
int i = create<int>();
int j = create<int>(5);
// double d = create<double>(); // Fails to compile
std::cout << i << " " << j << std::endl;
return 0;
}
Live example http://ideone.com/7a3uRZ
Edit: In response to your question, you could also make create a member function of a class, and pass along some of that data with the call or take action before or after
struct MyFactory
{
template<typename T, typename... Args>
T create(Args&&... args)
{
T ret = factory_impl<T>::create(data, std::forward<Args>(args)...);
// do something with ret
return ret;
}
Foo data; // Example
};
Given a template
template <int n>
void f(){...};
I know I can specialize it for specific values of n by doing:
template <>
void f<2>(){...};
But, is there a method which allows me to specialize it for all positive n?
I thought of doing the following
template <int n>
void f<n>(){
int dummy[n]; //invalid for n < 0
...
};
So for n<0 this code is invalid and the compiler would resort to the previous definition. Unfortunately, all I get is a redefinition of 'void f<n>()' error.
Note: I'm guessing this is probably not supported by the standard. I'm asking if there isn't some method (maybe some template metaprogramming) to achieve this effect.
One option would be to use another level of indirection. Define an auxiliary template that takes in two arguments - the number n and a bool representing whether or not n is negative, then specialize that template for when n is negative. Then, have your f function instantiate the template with the right arguments.
For example:
template <int n, bool isNegative> struct fImpl {
static void f() {
/* ... code for when n is positive ... */
}
};
template <int n> struct fImpl<n, true> {
static void f() {
/* ... code for when n is negative ... */
}
};
template <int n> void f() {
fImpl<n, (n < 0)>::f();
}
Another option is to use SFINAE overloading and the std::enable_if template class from C++11 (or Boost's equivalent);
template <int n> void f(typename std::enable_if<(n < 0)>::type* = 0) {
/* ... n is negative ... */
}
template <int n> void f(typename std::enable_if<(n >= 0)>::type* = 0) {
/* ... n is positive ... */
}
Each of these functions will only be available for overload resolution if n has the proper sign, so the correct version will always be called.
Hope this helps!