【问题标题】:Template parameter pack provokes error while explicit parameters not模板参数包会引发错误,而显式参数不会
【发布时间】:2015-04-21 21:25:51
【问题描述】:

以下代码 (live demo) 在 clang/gcc 上运行良好,但无法在 icc 和 msvc 上编译。

唯一的区别是在class A 中使用了模板参数包,而class B 是明确给出了所有模板参数。

正确的行为是什么?代码不正确吗?我错过了什么吗? 或者仅仅是 msvc/icc 不符合标准的事实?

更新

测试的编译器版本:

作品:

  • gcc 4.7.3、4.8.1、4.8.2、4.9.0、4.9.2
  • clang 3.3、3.4.1、3.5.0、3.5.1、3.6.0rc2

不起作用:

  • msvc-12.0 (2013) 更新 4
  • icc-13.0.1

代码

#include <unordered_map>

template <class Container>
struct A
{};

// the following won't compile on some compilers (msvc, icc)
template <class... Args>              // line 8
struct A<std::unordered_map<Args...>> // line 9
{
};

template <class Container>
struct B
{};

// the following compiles fine
template <class K, class T, class H, class P, class A>
struct B<std::unordered_map<K, T, H, P, A>>
{
};

int main(void)
{
    typedef std::unordered_map<int, int> my_map;
    A<my_map> a;
    B<my_map> b;
    return 0;
}

icc 错误

test-parameter-pack.cpp(9): error: too few arguments for class template "std::unordered_map"

struct A<std::unordered_map<Args...>>
^

test-parameter-pack.cpp(8): warning #885: template parameter "Args" is not used in or cannot be deduced from the template argument list of class template "A<<error-type>>"

template <class... Args>
^

msvc-12.0 更新 4 出错

test-parameter-pack.cpp
test-parameter-pack.cpp(9) : error C2976: 'std::unordered_map' : too few template arguments
C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\INCLUDE\unordered_map(79) : see declaration of 'std::unordered_map'
test-parameter-pack.cpp(10) : error C3203: 'unordered_map' : unspecialized class template can't be used as a template argument for template parameter 'Container', expected a real type
test-parameter-pack.cpp(8) : error C3211: 'A<int>' : explicit specialization is using partial specialization syntax, use template <> instead
test-parameter-pack.cpp(10) : see declaration of 'A<int>'

【问题讨论】:

  • 哪个版本的icc?
  • 我真的很想知道template &lt;class K, class... Args&gt; struct B&lt; std::unordered_map&lt;K, Args...&gt; &gt; {}; 是否适用于任何一个。
  • @WhozCraig 所有编译器(msvc 除外)都可以在gcc.godbolt.org 获得(参见现场演示)。 template &lt;class K, class... Args&gt; ... 呢,它在 msvc/icc-13 上也不起作用。
  • @WhozCraig: template &lt;class K, class... Args&gt; struct B&lt;std::unordered_map&lt;K, Args...&gt; &gt; {};&gt; 为 icc/msvc 工作。
  • 我觉得不错;可能是 ICC/MSVC 错误。

标签: c++ templates c++11 variadic-templates


【解决方案1】:

我认为这与您对A 的部分专业化是错误的事实有关。编译器无法推断出专用Container 的实际模板参数。

如果有人将Astd::unordered_map 实例化为容器类型,您似乎想做一些特别的事情(毕竟这是一种专业化)。我用以下代码在你的现场演示中使用 icc 编译它。

请注意,Container 现在是一个模板模板参数,它本身采用任意数量的模板参数。这允许将std::unordered_map 的使用检测为使用中的实际 容器类型。为了减少到最小的例子,我做了一些简化。

#include <unordered_map>

template <template <typename...> class Container, typename... Args>
struct A
{};

// the following won't compile on some compilers (msvc, icc)
template <typename... Args>
struct A<std::unordered_map, Args...>
{
};


int main(void)
{
    A<std::unordered_map, int, int> a;
    return 0;
}

【讨论】:

  • 感谢您的回答,但我的实际问题是:为什么我的代码错了(如果错了),哪个编译器是对的?
【解决方案2】:

我在使用 ICC 19.0.1 但使用 C++17 auto 模板参数时遇到了类似的问题。

解决方案是从值中拆分类型并单独推断:

void f(int, int);

//bugged
template<auto F>
struct BindFunc;

template<typename... Args, void(*X)(Args...)> //warning #885: template parameter "Args" is not used in or cannot be deduced from the template argument list of class template "BindFunc<X>"
struct BindFunc<X>
{

};

//correct
template<typename T, T X>
struct BindFunc2Impl;

template<typename... Args, void(*X)(Args...)>
struct BindFunc2Impl<void(*)(Args...), X>
{

};

template<auto F>
struct BindFunc2 : BindFunc2Impl<decltype(F), F>
{

};

//BindFunc<&f> a1; //error
BindFunc2<&f> a2;

https://gcc.godbolt.org/z/gTWzm5

【讨论】:

    猜你喜欢
    • 2022-08-11
    • 1970-01-01
    • 1970-01-01
    • 2016-11-23
    • 2021-10-19
    • 2021-10-17
    • 1970-01-01
    • 2019-06-08
    • 1970-01-01
    相关资源
    最近更新 更多