小编Yor*_*k B的帖子

为什么除非我添加括号,否则构造函数上的模板替换会失败?

我试图理解为什么除非添加括号,否则以下代码段的替换会失败:

template<typename T>
struct A {};

template<typename T>
struct B {
    B(A<T>);
};

template<typename T>
void example(A<T>, B<T>);

struct C {};

struct D {
    D(C);
};

void example2(C, D);

int main(int argc, char *argv[]) {
    example(A<int>{}, A<int>{}); // error
    example(A<int>{}, {A<int>{}}); // ok

    example2(C{}, C{}); // ok
    example2(C{}, {C{}}); // ok

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

请参阅此示例:https : //godbolt.org/z/XPqHww

因为example2我能够将 隐式传递C{}给 的构造函数而D没有任何错误。因为example我不允许隐式传递A<int>{}直到我添加括号。

什么定义了这种行为?

c++ templates c++11

6
推荐指数
1
解决办法
65
查看次数

是什么导致在使用包含冒号的类似函数的宏时出现这种编译器差异?

A()宏只会在 MSVC 上扩展,而不会在 GCC/Clang 上扩展,除非A()带有前缀,例如Test A().

通过在-E( /E) 标志 ( Godbolt.org )下运行以下代码段:

#define A() HelloWorld::
#define B() ::

A()
B()
Run Code Online (Sandbox Code Playgroud)

我们看到 MSVC 给出了以下输出:

HelloWorld::
::
Run Code Online (Sandbox Code Playgroud)

而 GCC/Clang 给出了不同的输出:

::
Run Code Online (Sandbox Code Playgroud)

但是然后运行这个片段:

#define A() HelloWorld::

A()
Test A()
Run Code Online (Sandbox Code Playgroud)

在所有 3 个编译器上为我们提供以下信息:

HelloWorld::
Test HelloWorld::
Run Code Online (Sandbox Code Playgroud)

为什么 GCC/Clang 输出缺少第一行?为什么它在Test A()写入时正确扩展所有事件?这是在标准中明确定义的,还是特定于编译器的?

c++ gcc clang visual-c++ precompile

5
推荐指数
1
解决办法
76
查看次数

标签 统计

c++ ×2

c++11 ×1

clang ×1

gcc ×1

precompile ×1

templates ×1

visual-c++ ×1