可变参数模板作为模板参数:扣可与海湾合作委员会,但不与锵(Variadic template as

2019-08-03 02:47发布

在编写既GCC 4.7.2和3.1锵一些C ++代码11,我跑进铿锵不是管理推导出模板参数,如果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马虎,铛哑巴,没有我的代码包含明确的行为或全部?

Answer 1:

锵试图推导出这个调用的参数:

processVariadic(SecondContainer<Element>{});

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

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

因此,执行与模板参数推导P = Container<Element>A = SecondContainer<Element, Element> 。 它可以立即推断出Container模板参数是SecondContainer

其次,它认为模板参数。 由于参数类型完全解决,锵认为,参数必须具有多种类型,或扣除不可能成功(不采取默认参数考虑在内)。 因此,它的标志扣除失败。


那么,什么是应该发生的? 在的话[temp.deduct.type]p8

模板类型参数T ,一个模板的模板参数TT或模板非类型自变数i的话可以推导出PA具有下列形式之一:
[...]
TT<T>
TT<i>
TT<>
其中,[...] <T>表示,其中至少一个参数包含一个模板参数列表T<i>表示,其中至少一个参数包含一个模板参数列表i<>表示没有参数包含一个模板的参数列表T或者i

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

如果P具有包含形式<T><i>然后每个参数Pi相应模板参数列表的P与相应参数进行比较Ai的相应的模板的参数列表的A

有两件事情在这里观察。 一个是这个规则不说,如果该列表会发生什么PiAi是不同的长度(因为他们在这种情况下),并共同演绎似乎是没有被检查不匹配的项目。 另一种是,该规则不应该无论如何其次,由于形式P不包含<T><i>它只是包含<>因为没有模板在它的参数)。


所以,锵是错误的拒绝这个代码。 我已经固定它r169475 。



文章来源: Variadic template as template parameter: deduction works with GCC but not with Clang