gpt4 book ai didi

c++ - 可变参数模板作为模板参数 : deduction works with GCC but not with Clang

转载 作者:IT老高 更新时间:2023-10-28 21:43:14 26 4
gpt4 key购买 nike

在使用 GCC 4.7.2 和 Clang 3.1 编译一些 C++11 代码时,我遇到了一个问题,即 Clang 无法推断出 GCC 成功的模板参数。在更抽象的形式中,代码如下所示:

src/test.cc:

struct Element {
};

template <typename T>
struct FirstContainer {
};

template <typename T, typename U = Element>
struct SecondContainer {
};

template <template <typename> class Container>
void processOrdinary(Container<Element> /*elements*/) {
}

template <template <typename, typename> class Container>
void processOrdinary(Container<Element, Element> /*elements*/) {
}

template <template <typename, typename...> class Container>
void processVariadic(Container<Element> /*elements*/) {
}

int main() {
// This function instantiation works in both GCC and Clang.
processOrdinary(FirstContainer<Element>{});
// This function instantiation works in both GCC and Clang.
processOrdinary(SecondContainer<Element>{});
// This function instantiation works in both GCC and Clang.
processVariadic(FirstContainer<Element>{});
// This function instantiation works in both GCC and Clang.
processVariadic<SecondContainer>(SecondContainer<Element>{});
// This function instantiation works in GCC but not in Clang.
processVariadic(SecondContainer<Element>{});
return 0;
}

通过阅读第 14.3.3 节中的示例和标准第 14.8.2 节中的规范,我认为推论应该有效,但我不能肯定地说。这是我从构建中得到的输出:

mkdir -p build-gcc/
g++ -std=c++0x -W -Wall -Wextra -Weffc++ -pedantic -c -o build-gcc/test.o src/test.cc
g++ -o build-gcc/test build-gcc/test.o
mkdir -p build-clang/
clang++ -std=c++11 -Weverything -Wno-c++98-compat -c -o build-clang/test.o src/test.cc
src/test.cc:34:3: error: no matching function for call to 'processVariadic'
processVariadic(SecondContainer<Element>{});
^~~~~~~~~~~~~~~
src/test.cc:21:6: note: candidate template ignored: failed template argument deduction
void processVariadic(Container<Element> /*elements*/) {
^
1 error generated.
make: *** [build-clang/test.o] Fel 1

为什么结果不同? GCC 是马虎、Clang 笨,我的代码是否包含未指定的行为或全部?

最佳答案

Clang 正在尝试推断此调用的参数:

processVariadic(SecondContainer<Element>{});

自从 SecondContainer有一个默认的模板参数,这相当于:

processVariadic(SecondContainer<Element, Element>{});

因此,它使用 P 执行模板参数推导= Container<Element>A = SecondContainer<Element, Element> .它可以立即推断出 Container模板参数为 SecondContainer .

接下来,它会考虑模板参数。由于参数类型是完全解析的,Clang 认为参数必须有尽可能多的类型,否则推导不可能成功(它不考虑默认参数)。所以它标记了一个扣除失败。


那么,应该发生什么?用 [temp.deduct.type]p8 的话来说,

A template type argument T, a template template argument TT or a template non-type argument i can be deduced if P and A have one of the following forms:
[...]
TT<T>
TT<i>
TT<>
where [...] <T> represents template argument lists where at least one argument contains a T, <i> represents template argument lists where at least one argument contains an i and <> represents template argument lists where no argument contains a T or an i.

为了匹配模板参数,我们转向 [temp.deduct.type]p9 :

If P has a form that contains <T> or <i>, then each argument Pi of the respective template argument list P is compared with the corresponding argument Ai of the corresponding template argument list of A.

这里有两件事要注意。一是这条规则没有说明如果列表 Pi 会发生什么。和 Ai是不同的长度(就像在这种情况下一样),常见的解释似乎是不检查不匹配的项目。另一个是无论如何都不应该遵循这个规则,因为 P 的形式不包含 <T><i> (它只包含 <> ,因为其中没有模板参数)。


因此,Clang 拒绝此代码是错误的。我已在 r169475 中修复它.

关于c++ - 可变参数模板作为模板参数 : deduction works with GCC but not with Clang,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13521163/

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