可变参数宏中的模板推导失败

问题描述

我的宏中的 decltype(__VA_ARGS__) 在仅针对单个参数而不是在传递多个参数时编译。

我想要实现的是根据运行时条件调用可变参数函数。 我的打印机的参数计算起来可能很昂贵,因此当我的条件为假时,我不想评估这些参数。

下面是一个最小的例子。也感谢您对改写此问题/描述的任何评论

#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,1,2,3); // doesn't compile
    
    // The macro should also handle pointers.
    PRINT_IF(&p,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_pointerprinter 转换为指针(如果还没有)。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...