【问题标题】:Casting a variadic parameter pack to (void)铸造Variadic参数包(空白)
【发布时间】:2013-11-01 04:27:10
【问题描述】:

我实际上遇到了以下问题:我希望能够使用-Wall -Wextra -Werror 进行构建,但是,以下代码会抱怨未使用的参数:

struct foo
{
    template <typename... Args>
    static void bar()
    { }

    template <typename T, typename ... Args>
    static void bar(T&& value, Args&& ... args)
    {
    #ifdef DEBUG
        std::cout << value;
        bar(std::forward<Args>(args)...);
    #endif
    }
};

第一个未使用的参数很容易修复:

    #ifdef DEBUG
        std::cout << value;
        bar(std::forward<Args>(args)...);
    #else // Shut the compiler up
        (void) value;
    #endif

我的问题是,我该如何处理剩下的 args?都没有

(void)(args...);

也没有

(void)(args)...;

会起作用,两者都抱怨参数包没有被扩展。

(这是在 GCC 4.7.3 下,如果这会对潜在的解决方案产生任何影响的话)。

【问题讨论】:

  • 不要命名它们,编辑它只会在你不进行调试构建时抱怨
  • @aaronman 他们必须被命名,因为他们(有条件地,取决于#DEBUG)被使用。
  • 老实说这听起来很难看,但你也可以把名字放在 ifdef 中

标签: c++ c++11 variadic-templates


【解决方案1】:

使用可变参数模板时,使用 sink 更干净:

struct sink { template<typename ...Args> sink(Args const & ... ) {} };


#ifdef DEBUG
    std::cout << value;
    bar(std::forward<Args>(args)...);
#else 
    sink { value, args ... }; //eat all unused arguments!
#endif

【讨论】:

  • 这可能是我将采用的解决方案,但我仍然有点好奇为什么问题中的代码不起作用。
  • @Yuushi:在某些情况下,可变参数可以自行解包。在您的上下文中,它们不会打开包装。见this topic
  • 只是为了表明我是多么的天真。我将刚刚声明 static bar() {} 非模板,并将 bar 转发器移动到模板版本中的 #endif 下方。适用于我的 Mac (clang) 上的迂腐警告,但我更喜欢你的解决方案。
  • @Nawaz,即使 sink 正确地吃掉了所有未使用的参数,我想它仍然会调用 copy ctor for sink。它会在已发布的版本中变为 nop 还是仍将创建为自动堆栈变量。对不起,我对 cpp 有点陌生
  • @HasanEmrahSüngü:好问题。 :竖起大拇指。 sink 的构造函数通过引用获取所有参数,因此您传递给它的未使用的参数都不会复制!另外,我很确定如果你使用-O2 或更高版本,它会是nop
【解决方案2】:

你真的可以在这里使用条件命名。

#ifdef DEBUG
#define DEBUG_NAME(x) x
#else
#define DEBUG_NAME(x)
#endif

static void bar(T&& DEBUG_NAME(value), Args&& DEBUG_NAME(args)) {}

【讨论】:

  • 身体仍然需要#ifdef DEBUG,但不再需要#else
【解决方案3】:

解决此问题的另一种方法是移动#define 以创建省略参数名称的替代模板:

#ifdef DEBUG
    template <typename T, typename ... Args>
    static void bar(T&& value, Args&& ... args)
    {
        std::cout << value;
        bar(std::forward<Args>(args)...);
    }
#else 
    template <typename T, typename ... Args>
    static void bar(T&& value, Args&& ...)
    {
    }
#endif

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-04-03
    • 1970-01-01
    • 2015-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-18
    相关资源
    最近更新 更多