相关疑难解决方法(0)

Variadic模板包扩展

我正在尝试学习可变参数模板和函数.我无法理解为什么这段代码不能编译:

template<typename T>
static void bar(T t) {}

template<typename... Args>
static void foo2(Args... args)
{
    (bar(args)...);
}

int main()
{
    foo2(1, 2, 3, "3");
    return 0;    
}
Run Code Online (Sandbox Code Playgroud)

当我编译它失败时出现错误:

错误C3520:'args':必须在此上下文中扩展参数包

(在功能上foo2).

c++ templates variadic-templates c++11

69
推荐指数
4
解决办法
4万
查看次数

请问"variableName;" C++声明在任何时候都是无操作的?

在C++中,有时会定义一个变量,但不会使用.这是一个示例 - 与COM_INTERFACE_ENTRY_FUNC_BLINDATL宏一起使用的函数:

HRESULT WINAPI blindQuery( void* /*currentObject*/, REFIID iid, void** ppv, DWORD_PTR /*param*/ ) 
{
    DEBUG_LOG( __FUNCTION__ ); //DEBUG_LOG macro expands to an empty string in non-debug
    DEBUG_LOG( iid );
    iid; // <<<<<<<----silence compiler warning
    if( ppv == 0 ) {
        return E_POINTER;
    }
    *ppv = 0;
    return E_NOINTERFACE;
}
Run Code Online (Sandbox Code Playgroud)

在上面的示例中,iid参数与DEBUG_LOG宏一起使用,在非调试配置中扩展为空字符串.因此,iid不能选择在签名中注释或删除变量名称.当编译非调试配置时,编译器会产生C4100: 'iid' : unreferenced formal parameter警告,因此为了使警告静音iid;,添加了被认为是无操作的语句.

问题如下:如果我们有以下任何声明:

 CSomeType variableName; //or
 CSomeType& variableName; //or
 CSomeType* variableName;
Run Code Online (Sandbox Code Playgroud)

将在C++代码中的以下语句:

variableName; …
Run Code Online (Sandbox Code Playgroud)

c++ compiler-warnings

20
推荐指数
1
解决办法
2813
查看次数

为什么无效转换功能很奇怪?

为什么以下程序

#include <iostream>

struct C
{
    operator int()
    {
        std::cout << "C::operator int()" << std::endl;
        return 0;
    }
    operator void()
    {
        std::cout << "C::operator void()" << std::endl;
    }
};

int main()
{
    C c;
    (int)c;
    (void)c;
    // this does run the function:
    // c.operator void();
}
Run Code Online (Sandbox Code Playgroud)

输出这个

C::operator int()
Run Code Online (Sandbox Code Playgroud)

而不是这个?

C::operator int()
C::operator void()
Run Code Online (Sandbox Code Playgroud)

coliru现场演示.

一如既往,直接的回答是"因为标准是这么说的".

C++ 11标准,§12.3.2

转换函数从不用于将(可能是cv限定的)对象转换为(可能是cv限定的)相同的对象类型(或对它的引用),转换为该类型的(可能是cv限定的)基类(或引用它)或(可能是cv-qualified)void.

那么为什么标准会这样说呢?使空洞转换功能成为特殊情况有什么好处?

其他说明见脚注116:

这些转换被视为标准转换,用于重载解析(13.3.3.1,13.3.3.1.4),因此初始化(8.5)和显式转换(5.2.9).转换为void不会调用任何转换函数(5.2.9).即使从未直接调用执行转换,也可以声明此类转换函数,并且可以通过调用基类中的虚拟转换函数来实现.

我只是习惯于(void)对有关未使用变量的编译器警告进行静音.它看起来基本上也是其他人使用它的东西.

为什么将未使用的返回值转换为void?

如果void转换函数遵循典型的转换函数规则,则可能会出现意外情况,但对于任何具有副作用的转换函数而言都是如此,并且创建这些意外将由程序员自行决定.

c++ type-conversion language-lawyer c++11

8
推荐指数
0
解决办法
131
查看次数

SFINAE:'static_cast <void>()'或',void()'?

在任意类型上执行SFINAE时,通常需要将表达式的结果转换为void.我已经看到了两种方法; 演员无效:

(void)(expr)    // or static_cast<void>(expr)
Run Code Online (Sandbox Code Playgroud)

或者,使用带有void prvalue RHS的逗号运算符:

(expr), void()
Run Code Online (Sandbox Code Playgroud)

我的理解是,在两种情况下都要expr评估(对于良好的形式,在非评估的上下文中)和结果(或结果类型,在非评估的上下文中)被丢弃; 在任何一种情况下,即使是病理类也不可能T覆盖T::operator void()operator,(T, void).(参见:为什么是"运营商无效"不投语法调用?,什么的'无效()'中的'自动F(PARAMS) - > decltype(...,无效())'呢?).

也就是说,这两个成语是等价的,还是在某种情况下,一个人应该优先于另一个(可能是非标准的编译器)?如果没有,是否有任何理由(例如可理解性)偏好一个而不是另一个?

c++ void decltype sfinae

8
推荐指数
1
解决办法
316
查看次数