gcc 4.4 的模板模板参数和可变参数模板

发布于 2024-12-21 10:34:55 字数 1492 浏览 1 评论 0原文

我在 Debian squeeze 上使用 gcc 4.4。考虑以下代码。

#include <map>
#include <string>
using std::map;
using std::string;

// Args lets the user specify additional explicit template arguments
template <typename T,
      template <typename T, typename... Args> class C,
      typename... Args>
C<T, Args...> foo()
{
  C<T, Args...> x;
  return x;
}

int main(void)
{
  map<string, int> a = foo<string, map, int>();
}

所以,这里的想法是 T 匹配 stringC 匹配 map,模板参数包 Args 匹配 int。我可能有一些语法错误,如果有请纠正。特别是,如果希望 class C 中的第一个模板参数与 T 匹配,其余部分与模板参数包 Args 匹配,则 <代码>模板<类型名称T,类型名称...参数> C 类的语法正确吗?

这会给出错误

In function 'int main()':
post.cc:18: error: no matching function for call to 'foo()'

这似乎与问题可变参数模板和完美转发。这个问题表明这是一个 gcc 错误,但也许我错误地认为这些问题是关于同一件事的。

请温柔一点。我对可变参数模板的了解还不到 12 小时;我只是想重写一些旧的 C++ 代码以减少重复。我也有一段时间没有接触过 C++ 了。如果有解决方法,请告诉我。谢谢。

编辑:可变参数模板和完美转发评论中建议的解决方法Ise Wisteria 为我工作,这表明这是同一个错误。当然,我现在就是 (a) 想知道这个解决方法有多脆弱,(b) 为什么它有效,以及是什么促使 Ise 想到它。 虽然我猜只有一诚可以回答最后一点。 :-)

I'm using gcc 4.4 on Debian squeeze. Consider the following code.

#include <map>
#include <string>
using std::map;
using std::string;

// Args lets the user specify additional explicit template arguments
template <typename T,
      template <typename T, typename... Args> class C,
      typename... Args>
C<T, Args...> foo()
{
  C<T, Args...> x;
  return x;
}

int main(void)
{
  map<string, int> a = foo<string, map, int>();
}

So, the idea here is that T matches string, C matches map, and the template parameter pack Args matches int. I may have some of the syntax wrong, please correct if so. In particular, if one wants the first template argument in class C to match T and the rest to match the template parameter pack Args, is template <typename T, typename... Args> class C the correct syntax?

This gives the error

In function 'int main()':
post.cc:18: error: no matching function for call to 'foo()'

This appears to be similar to the question Variadic template templates and perfect forwarding. That question suggests that this is a gcc bug, but maybe I am mistaken in thinking these questions are about the same thing.

Please be gentle. My knowledge of variadic templates is less than 12 hours old; I was just trying to rewrite some old C++ code to reduce duplication. It has also been a while since I did any C++. If there is a workaround, please let me know. Thanks.

EDIT: The workaround suggested in the comments of Variadic template templates and perfect forwarding by Ise Wisteria worked for me, which suggests that this is the same bug. Of course, I'm am now
(a) wondering how fragile this workaround is and (b) why it works, and what motivated Ise to think of it.
Though I guess only Ise can answer the last bit. :-)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

你的他你的她 2024-12-28 10:34:56

我认为可变参数模板参数不能与 g++4.4 中的非可变参数相匹配,因此您需要使用非可变版本重载 foo 函数。

另请记住,map 实际上有两个以上的模板参数,因此也不会匹配新的 foo 函数。

添加到您的示例中应该可以澄清这一点:

#include <map>
#include <string>
using std::map;
using std::string;

// Args lets the user specify additional explicit template arguments
template <typename T,
          template <typename T, typename... Args> class C,
          typename... Args>
C<T, Args...> foo() {
  C<T, Args...> x;
  return x;
}

template<typename T, template<typename, typename> class C, typename Arg>
C<T, Arg> foo() {
  return C<T, Arg>();
}

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

template<typename T, typename Arg> class B {};

int main(void) {
  map<string, int> a = foo<string, map, int>(); // fails.
  A<string, int> x = foo<string, A, int>();
  B<string, int> y = foo<string, B, int>();
}

I don't think variadic template parameters can match non-variadic arguments in g++4.4, so you need to overload your foo function with a non-variadic version.

Also keep in mind that map actually has more than two template parameters, and therefor wont match the new foo-function either.

This addition to your example should clarify it:

#include <map>
#include <string>
using std::map;
using std::string;

// Args lets the user specify additional explicit template arguments
template <typename T,
          template <typename T, typename... Args> class C,
          typename... Args>
C<T, Args...> foo() {
  C<T, Args...> x;
  return x;
}

template<typename T, template<typename, typename> class C, typename Arg>
C<T, Arg> foo() {
  return C<T, Arg>();
}

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

template<typename T, typename Arg> class B {};

int main(void) {
  map<string, int> a = foo<string, map, int>(); // fails.
  A<string, int> x = foo<string, A, int>();
  B<string, int> y = foo<string, B, int>();
}
江南月 2024-12-28 10:34:55

正如编辑中所讨论的,我的问题似乎与链接的问题存在相同的错误, Variadic模板模板和完美转发。特别是,链接中给出的解决方法也适用于我的情况。修改后的工作代码如下:

#include <map>
#include <string>
using std::map;
using std::string;

template <typename T,
      template <typename T, typename... Args> class C,
      typename... Args>
struct X
{
  typedef C<T, Args...> type;
};

template <typename T,
      template <typename T, typename... Args> class C,
      typename... Args>
typename X<T, C, Args...>::type foo()
{
  C<T, Args...> x;
  return x;
}

int main(void)
{
  map<string, int> a = foo<string, map, int>();
}

As discussed in the edits, my question appears to tickle the same bug as the linked question, Variadic template templates and perfect forwarding. In particular, the workaround given there in a link also works in my case. The modified code that works is as follows:

#include <map>
#include <string>
using std::map;
using std::string;

template <typename T,
      template <typename T, typename... Args> class C,
      typename... Args>
struct X
{
  typedef C<T, Args...> type;
};

template <typename T,
      template <typename T, typename... Args> class C,
      typename... Args>
typename X<T, C, Args...>::type foo()
{
  C<T, Args...> x;
  return x;
}

int main(void)
{
  map<string, int> a = foo<string, map, int>();
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文