gpt4 book ai didi

c++ - 实例化成员模板函数时的 Buggy (?) 编译器行为

转载 作者:搜寻专家 更新时间:2023-10-31 00:51:46 24 4
gpt4 key购买 nike

编辑 - 测试这个的确切最小代码在我下面的原始帖子中,但它是两个 block 。抱歉,这里是一体的。注释掉 main 中的实例化然后一次取消对它们的注释显示了我在这篇文章中描述的行为。

template <typename... TsOuter>
struct Outer
{
template <TsOuter...>
static void InnerFunc() {};
};

int main(int argc, char** argv)
{
Outer<int, int>::InnerFunc<1, 1>(); // Should work. Works on MSVC, fails on g++
Outer<int, int>::InnerFunc(); // Should fail. Works on both compilers
Outer<int, int>::InnerFunc<>(); // Should fail. Works on both compilers
Outer<int, int>::InnerFunc<1>(); // Should fail. Works on MSVC, fails on g++
Outer<int, int>::InnerFunc<1, 1, 1>(); // Should fail. Fails on both compilers
Outer<int, int>::InnerFunc<nullptr, nullptr>(); // Should fail. Fails on both compilers.
}

编辑 - 我没有包含我正在使用的编译器版本,我看到了我描述的行为:

  • 海湾合作委员会:7.3.0
  • MSVC:Microsoft Visual Studio Professional 2017,版本 15.7.4

我看到我认为在 Microsoft C++ 和 g++ 中都是错误的编译器行为。当我认为编译器应该编译成功时,编译器会给出错误,而当我认为它们应该给出错误时,编译器会编译成功。两个编译器之间的错误 (?) 编译器行为并不完全相同。

我的问题是:编译器确实有问题,还是我的理解有问题?规范是否说明以下代码的编译器行为未定义?

当具有参数包模板参数的模板类定义成员函数模板时,就会出现此问题,使用类的参数包作为其模板参数。当我实例化那个成员函数模板时

  • 当模板参数与模板参数的定义正确匹配时,我会出错
  • 反之亦然:当模板参数与其模板参数不匹配时,我编译成功。

奇怪的是,如果成员模板是成员模板而不是成员模板函数,那么一切都完全符合我的预期。

这是模板类定义:

template <typename... TsOuter>
struct Outer
{
template <TsOuter...>
struct InnerClass {};

template <TsOuter...>
static void InnerFunc() {};
};

注意 InnerClass 的模板参数和 InnerFunc取决于 Outer 的模板参数.

我实例化 Outer作为Outer<int, int> .这使得声明 InnerClass

template <int,int>
struct InnerClass {};

InnerFunc的声明

template <int, int>
static void InnerFunc() {};

实例化时InnerClass ,编译器的行为(MSVC 和 g++)符合我的理解:

Outer<int, int>::InnerClass<1, 1> x2 {};              // OK
Outer<int, int>::InnerClass x2 {}; // ERROR - No template arguments provided for InnerClass
Outer<int, int>::InnerClass<> x2 {}; // ERROR - <> does not match <int, int> (to few template arguments)
Outer<int, int>::InnerClass<1> x1 {}; // ERROR - <1> does not match <int, int> (to few template arguments)
Outer<int, int>::InnerClass<1, 1, 1> x3 {}; // ERROR - <1,1,1> does not match <int, int> (to many template arguments)
Outer<int, int>::InnerClass<nullptr, nullptr> x4 {}; // ERROR - <nullptr, nullptr> does not match <int, int> (template argument types do not match template parameter types)

但是,对于 InnerFunction他们有区别。我对InnerFunction的期望InnerClass 相同.但我看到的是:

Outer<int, int>::InnerFunc<1,1>();               // Should work.  Works on MSVC, fails on g++
Outer<int, int>::InnerFunc(); // Should fail. Works on both compilers
Outer<int, int>::InnerFunc<>(); // Should fail. Works on both compilers
Outer<int, int>::InnerFunc<1>(); // Should fail. Works on MSVC, fails on g++
Outer<int, int>::InnerFunc<1,1,1>(); // Should fail. Fails on both compilers
Outer<int, int>::InnerFunc<nullptr, nullptr>(); // Should fail. Fails on both compilers.

如果Outer具有非可变参数模板参数,我没有看到这个问题 - 所有 InnerClass 都按预期工作和 InnerFunction .

鉴于我在这里描述的编译器的行为,我是否正确地认为它们都有错误?如果是这样的话,它们对我来说似乎是非常重要的错误。

谢谢!

最佳答案

这确实是 gcc 中的编译器错误。

下面是用来测试的

https://godbolt.org/z/8ZZt-B

template <typename... TsOuter>
struct Outer
{
template <TsOuter... n>
static void InnerFunc() {
static int i[2] = { n... };
};
};

int main() {
typedef Outer<int, int> t;

t::InnerFunc<1, 1>();
}

这在 clang 和 msvc 中编译得很好。

但是在 gcc 中错误是:

<source>:13:24: error: no matching function for call to 'Outer<int, int>::InnerFunc<1, 1>()'
13 | t::InnerFunc<1, 1>();
| ^
<source>:5:17: note: candidate: 'template<TsOuter ...n> static void Outer<TsOuter>::InnerFunc() [with TsOuter ...n = {n ...}; TsOuter = {int, int}]'
5 | static void InnerFunc() {
| ^~~~~~~~~
<source>:5:17: note: template argument deduction/substitution failed:
<source>:13:24: error: wrong number of template arguments (2, should be 1)
13 | t::InnerFunc<1, 1>();
| ^

这表明 gcc 认为应该有一个参数,而不是 2 个,错误地没有扩展参数包。

如果您确实传递了一个参数而不是 2 个:

https://godbolt.org/z/9fZZZC

t::InnerFunc<1>();
<source>:13:21: internal compiler error: tree check: accessed elt 1 of tree_vec with 0 elts in tsubst_pack_expansion, at cp/pt.c:12169
13 | t::InnerFunc<1>();
| ^

我实际上不确定参数包作为模板参数应该如何工作,但它绝对不应该是内部编译器错误。我无法在本地 g++ 安装上重现此错误,但错误被奇怪地切断了(打印“模板参数推导/替换失败:”然后什么也没有)

关于c++ - 实例化成员模板函数时的 Buggy (?) 编译器行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54151120/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com