【问题标题】:template deduction failure in variadic macro可变参数宏中的模板推导失败
【发布时间】:2021-03-10 15:26:10
【问题描述】:

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

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

下面是一个最小的示例。任何改写这个问题/描述的 cmets 也很感激。

#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;
}

【问题讨论】:

  • 问题是当你需要decltype(1), decltype(2), decltype(3)decltype(__VA_ARGS__)变成decltype(1, 2, 3)
  • 1.你不需要这个 decltype。 2. decltype 是一元的,所以如果你把__VA_ARGS__ 放在额外的括号中,它就可以工作。
  • 有什么理由使用std::invoke 而不是在printer 上调用print
  • 为什么要使用宏?我看不出有任何理由在这里使用它。
  • @Holt 处理printer 可以是指针或实例的情况

标签: c++ variadic-templates template-argument-deduction variadic-macros


【解决方案1】:

您可以这样做以避免必须找到模板重载:

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__)

这让-&gt;print 推导出模板参数以避免必须找到重载,并且只需使用add_pointerprinter 转换为指针(如果它还没有)。

【讨论】:

  • 为什么不只是if(cond) printer.print(__VA_ARGS__)
  • @NathanOliver 因为 OP 想要处理 printer 是指针的情况(请参阅问题中的 cmets)。
  • 鉴于转发参考,您应该remove_reference_t&lt;T&gt;。因为对于左值指针变量TPrinter*&amp;
  • 我会走另一条路deref_when_possible :-)
猜你喜欢
  • 2020-06-05
  • 2012-10-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多