可变参数宏中的模板推导失败
template deduction failure in variadic macro
我的宏中的 decltype(__VA_ARGS__) 仅针对单个参数编译,而不是在传递多个参数时编译。
我想要实现的是根据运行时条件调用可变参数函数。
我的打印机的参数计算起来可能很昂贵,因此我不想在我的条件为假时不评估这些参数。
下面是一个最简单的示例。任何对此 question/description 的改写意见也表示赞赏。
#include <iostream>
#include <utility>
#include <functional>
#define PRINT_IF(printer, cond, ...) if(cond) std::invoke(&Printer::print<decltype(__VA_ARGS__)>, printer, __VA_ARGS__)
// Some Fixed Printer Interface ...
class Printer{
public:
void print(){}
template <typename T, typename... Types>
void print(T&& var1, Types&&... var2)
{
std::cout << var1 << std::endl ;
print(var2...);
}
};
int main()
{
Printer p;
PRINT_IF(p, returns_false(), very_expensive_string()); // compiles and expensive operation skipped
PRINT_IF(p, true, 1); // compiles
PRINT_IF(p, true, 1, 2, 3); // doesn't compile
// The macro should also handle pointers.
PRINT_IF(&p, true, 1, 2, 3);
return 0;
}
您可以这样做以避免发现模板过载:
template <class T>
auto add_pointer(T&& t) {
if constexpr (std::is_pointer_v<std::remove_reference_t<T>>) {
return t;
}
else {
return &t;
}
}
#define PRINT_IF(printer, cond, ...) if(cond) add_pointer(printer)->print(__VA_ARGS__)
这让 ->print
推导模板参数以避免必须找到重载,如果还没有,只需使用 add_pointer
将 printer
转换为指针。
我的宏中的 decltype(__VA_ARGS__) 仅针对单个参数编译,而不是在传递多个参数时编译。
我想要实现的是根据运行时条件调用可变参数函数。 我的打印机的参数计算起来可能很昂贵,因此我不想在我的条件为假时不评估这些参数。
下面是一个最简单的示例。任何对此 question/description 的改写意见也表示赞赏。
#include <iostream>
#include <utility>
#include <functional>
#define PRINT_IF(printer, cond, ...) if(cond) std::invoke(&Printer::print<decltype(__VA_ARGS__)>, printer, __VA_ARGS__)
// Some Fixed Printer Interface ...
class Printer{
public:
void print(){}
template <typename T, typename... Types>
void print(T&& var1, Types&&... var2)
{
std::cout << var1 << std::endl ;
print(var2...);
}
};
int main()
{
Printer p;
PRINT_IF(p, returns_false(), very_expensive_string()); // compiles and expensive operation skipped
PRINT_IF(p, true, 1); // compiles
PRINT_IF(p, true, 1, 2, 3); // doesn't compile
// The macro should also handle pointers.
PRINT_IF(&p, true, 1, 2, 3);
return 0;
}
您可以这样做以避免发现模板过载:
template <class T>
auto add_pointer(T&& t) {
if constexpr (std::is_pointer_v<std::remove_reference_t<T>>) {
return t;
}
else {
return &t;
}
}
#define PRINT_IF(printer, cond, ...) if(cond) add_pointer(printer)->print(__VA_ARGS__)
这让 ->print
推导模板参数以避免必须找到重载,如果还没有,只需使用 add_pointer
将 printer
转换为指针。