I want to write a function that will do an operation based on the types, not arguments, of a function. As such, the function receives no template based arguments. The general gist is something like this:
#include <iostream>
void func() {
std::cout<<"End marker\n";
}
template <typename Type, typename... T>
void func() {
std::cout<<"Type sizeof "<<sizeof(T)<<"\n";
func<T...>();
}
int main() {
func<int, int, int>();
}
Which, of course, doesn't compile. I've tried doing this:
template <typename Type, typename... T>
void func() {
std::cout<<"Type sizeof "<<sizeof(T)<<"\n";
if( sizeof...(T)!=0 )
func<T...>();
}
This does not work, however. The func<T...>
may not get evaluated, but it does need to be compilable.
Is there a way to do this that I'm missing?
You can make the non-template function func
into a variadic template function which accepts zero template arguments. Then let SFINAE move away this template function when the number of arguments is not zero.
Following should work:
#include <iostream>
#include <type_traits>
template <typename... Ts>
typename std::enable_if<sizeof...(Ts) == 0>::type func() {
std::cout<<"End marker\n";
}
template <typename T, typename... Ts>
void func() {
std::cout << "Type sizeof " << sizeof(T) << "\n";
func<Ts...>();
}
int main() {
func<int, int, int>();
}
However, please note that:
(8) The validity of a template may be checked prior to any instantiation. [ Note: Knowing which names are type names allows the syntax of every template to be checked in this way. — end note ] The program is ill-formed, no diagnostic required, if: [..] (8.3) every valid specialization of a variadic template requires an empty template parameter pack...
Source here
UPDATE
This would work too:
#include <iostream>
#include <type_traits>
void func() {
std::cout<<"End marker\n";
}
template <typename T, typename... Ts>
void func() {
std::cout << "Type sizeof " << sizeof(T) << "\n";
if constexpr (0 == sizeof...(Ts))
func();
else
func<Ts...>();
}
int main() {
func<int, int, int>();
}
You can make your original setup work by making func
a "template function" (that doesn't actually use the template) like:
template<int = 0>
void func() {
std::cout<<"End marker\n";
}
template <typename Type, typename... T>
void func() {
std::cout<<"Type sizeof "<<sizeof(Type)<<"\n";
func<T...>();
}
And your second one can work by using if constexpr
, so func<>()
isn't compiled.
With fold-expression (in C++17), you might do:
template <typename... Ts>
void func()
{
((std::cout << "Type sizeof " << sizeof(Ts) << "\n"), ...);
std::cout << "End marker\n";
}
That can even be done in C++11, but it would be more verbose:
template <typename... Ts>
void func()
{
const int dummy[] = {((std::cout << "Type sizeof " << sizeof(Ts) << "\n"), 0)...};
static_cast<void>(dummy); // Avoid warning for unused variable.
std::cout <<"End marker\n";
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.