gpt4 book ai didi

c++ - 对于曾经在 gcc5 中工作的情况,在 gcc6 的部分特化中无法推导出模板参数

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:38:27 25 4
gpt4 key购买 nike

此代码在 gcc6 中导致错误(但在 gcc 4.8、5.2 和 clang 3.6 中工作正常):

template <typename T>
struct outer
{
template <typename U>
struct inner
{

};
};


template <typename T>
struct is_inner_for
{

template <typename Whatever>
struct predicate
{
static constexpr bool value = false;
};

template <typename U>
struct predicate<typename outer<T>::template inner<U>>
{
static constexpr bool value = true;
};
};

static_assert(
is_inner_for<int>::template predicate<
outer<int>::inner<double>
>::value,
"Yay!"
);

错误是:

main.cpp:22:9: error: template parameters not deducible in partial specialization:
struct predicate<typename outer<T>::template inner<U>> : std::true_type
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
main.cpp:22:9: note: 'U'
^~~~~~~~~~~~~

命令行是:

g++ -std=c++1y -c main.cpp

参见 godbolt output here .

我在这里提交了 gcc 错误报告:https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70141

但是它被标记为无效(我相信是错误的)。 outer<T>predicate 中使用此时是具体类型,因此它不是非推导上下文。

标准中是否有任何内容阻止这是有效的 C++ 代码?

最佳答案

我怀疑这是 gcc 6.0 中的错误,以及 clang 3.9 中的错误警告(警告很奇怪 - 因为警告暗示不会选择部分特化,但如果不选择,静态断言会触发器)。


来自 [temp.class.spec.match]:

A partial specialization matches a given actual template argument list if the template arguments of the partial specialization can be deduced from the actual template argument list

我们可以推断出 Utypename outer<T>::template inner<U>来自 outer<int>::inner<double>

来自 [temp.deduct.type]:

If a template parameter is used only in non-deduced contexts and is not explicitly specified, template argument deduction fails.

The non-deduced contexts are:
— The nested-name-specifier of a type that was specified using a qualified-id.
— [...]

但是这里的 nested-name-specifiedtypename outer<T> ,它不包含我们要推断的类型。其他非推导上下文均不适用。所以演绎应该在这里成功。

考虑以下等效情况:

#include <utility>

template <class >
struct outer
{
template <class U> struct inner {};
};

template <class T>
struct bar {
template <class U> std::false_type foo(U const&);
template <class U> std::true_type foo(typename outer<T>::template inner<U> const&);
};


int main() {
static_assert(decltype(bar<int>{}.foo(outer<int>::inner<double>{}))::value, "!");
}

gcc 6.0 和 clang 3.9 都在没有警告的情况下编译此代码 - 但这是在原始示例的部分特化中会发生的相同类型的推导。

关于c++ - 对于曾经在 gcc5 中工作的情况,在 gcc6 的部分特化中无法推导出模板参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35875829/

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