不带参数的可变参数模板函数
Variadic template function with no arguments
我想编写一个函数,该函数将根据函数的类型而不是参数执行操作。因此,该函数不接收基于模板的参数。一般要点是这样的:
#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>();
}
这当然不能编译。我试过这样做:
template <typename Type, typename... T>
void func() {
std::cout<<"Type sizeof "<<sizeof(T)<<"\n";
if( sizeof...(T)!=0 )
func<T...>();
}
但是,这不起作用。 func<T...>
可能无法评估,但它确实需要可编译。
有没有我想念的方法?
您可以将非模板函数 func
变成接受零模板参数的可变参数模板函数。然后让SFINAE在参数个数不为0的时候把这个模板函数搬走
以下应该有效:
#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>();
}
但是,请注意:
(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...
来源here
更新
这也行得通:
#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>();
}
您可以通过将 func
设为 "template function"(实际上并不使用模板)来使您的原始设置生效,例如:
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...>();
}
而您的第二个可以使用 if constexpr
工作,因此 func<>()
未编译。
使用折叠表达式(在 C++17 中),你可以这样做:
template <typename... Ts>
void func()
{
((std::cout << "Type sizeof " << sizeof(Ts) << "\n"), ...);
std::cout << "End marker\n";
}
这甚至可以在 C++11 中完成,但会更冗长:
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";
}
我想编写一个函数,该函数将根据函数的类型而不是参数执行操作。因此,该函数不接收基于模板的参数。一般要点是这样的:
#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>();
}
这当然不能编译。我试过这样做:
template <typename Type, typename... T>
void func() {
std::cout<<"Type sizeof "<<sizeof(T)<<"\n";
if( sizeof...(T)!=0 )
func<T...>();
}
但是,这不起作用。 func<T...>
可能无法评估,但它确实需要可编译。
有没有我想念的方法?
您可以将非模板函数 func
变成接受零模板参数的可变参数模板函数。然后让SFINAE在参数个数不为0的时候把这个模板函数搬走
以下应该有效:
#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>();
}
但是,请注意:
(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...
来源here
更新
这也行得通:
#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>();
}
您可以通过将 func
设为 "template function"(实际上并不使用模板)来使您的原始设置生效,例如:
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...>();
}
而您的第二个可以使用 if constexpr
工作,因此 func<>()
未编译。
使用折叠表达式(在 C++17 中),你可以这样做:
template <typename... Ts>
void func()
{
((std::cout << "Type sizeof " << sizeof(Ts) << "\n"), ...);
std::cout << "End marker\n";
}
这甚至可以在 C++11 中完成,但会更冗长:
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";
}