带有常量模板参数的模板类模板

8
我不明白为什么这个代码无法编译:
struct  A
{};  

template<class T> 
struct  B
{};  

template<template<class> class T1, class T2> 
struct C
{};

int
main  (int ac, char **av)
{
  typedef B<double> b;              //compiles
  typedef B<const double> b_const;  //compiles
  typedef B<A> ba;                  //compiles
  typedef B<const A> ba_const;      //compiles

  typedef C<B,double> c1;           //compiles
  typedef C<B,const double> c2;     //compiles
  typedef C<const B,double> c3;     //ISO C++ forbids declaration of ‘type name’ with no type
}

我发现对标准的参考有点晦涩难懂。

我需要改动些什么才能使其编译通过?

编辑:

编译器详情(似乎相关):

Using built-in specs.
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu/Linaro 4.4.4-14ubuntu5' --with-bugurl=file:///usr/share/doc/gcc-4.4/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.4 --enable-shared --enable-multiarch --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.4 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc --disable-werror --with-arch-32=i686 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 4.4.5 (Ubuntu/Linaro 4.4.4-14ubuntu5) 

编辑2:

为了解释,我正在尝试做这样的事情:

template<template<class> class TheContainer, class T> 
struct Iterator

template<class T> 
struct  Container

typedef Iterator<Container, double> iterator;
typedef Iterator<const Container, double> const_iterator;

非模板容器的技术可以在boost文档的结尾找到:http://www.boost.org/doc/libs/1_46_1/libs/iterator/doc/iterator_facade.html

我想解决方案就是不要嵌套模板。回想起来似乎很明显。


这篇文章有一个很棒的主题 :) - Laserallan
@Laserallan 它让我怀念 Perl。 - Tom
1
我需要改变什么才能使它编译通过?显然,你需要删除最后一个typedef。更严肃地说,你试图通过这样做来实现什么? - James McNellis
@James 我正在尝试为一个模板类编写迭代器:我正在遵循Boost教程:http://www.boost.org/doc/libs/1_46_1/libs/iterator/doc/iterator_facade.html。他们通过使用一个模板来传递容器和const容器给迭代器(页面下方约2/3处)编写了迭代器的const和非const版本。我想为一个模板化的容器使用相同的技术。 - Tom
@James - 编辑了问题,使动机更加清晰。 - Tom
4个回答

4
C的第一个参数不是一个类型,因此将const类型作为其参数传递是没有意义的。模板不能是const或non-const,只有类型才能是const或non-const。那么"const B"到底是什么意思呢?
"const int" 有意义。 "const vector" 有意义,"vector" 也有意义。但是"const vector"会意味着什么呢?
(小心点:在看到这个问题之前,我甚至不知道模板模板类。)
为了使这更具体化,想象B和C是:
template<class T>
struct  B
{
        T t;
};      

template<template<class> class T1, class T2>
struct C
{
        T2 t2;
        T1<T2> t1;
};

c2将是一种类型

C<B,const double>   
==>   struct { const double t2; T1<const double> t1;}
==> struct { const double t2; struct { const double b; } t1;}

你希望c3是什么?t1本身是const,而t1.b是non-const吗?我想这很有道理。


谢谢,是的,现在看起来很明显。我需要明确地打出我想要模板执行的内容。 - Tom
感谢您让我了解模板模板! - Aaron McDaid

2

这段代码在VS2010中是可以编译的。我不知道你用的是哪个编译器,但建议你检查一下编译器开发者的错误数据库,看看是否有类似的错误已经被注册。

我会在GCC中尝试一下。


好的,GCC(4.5.1)确实会出现错误。我想我们需要等待某个具备标准知识的人来确定这是标准行为还是一个bug。


CLang(2.8)也会出现相同的错误(并且错误消息完全相同)。


谢谢您的尝试 - 我已经发布了我的gcc -v。我现在会去看一下错误数据库。 - Tom
没问题。我开始搜索,但是这个错误信息在很多情况下都会出现,其中找不到类型,所以很难找到错误。我认为可能VS2010也太宽容了。没有标准知识很难知道。 - Klaim

1

我猜B不能是const,因为此时它没有真正的类型,编译器不知道应该是什么const。除了省略const之外,我想不出其他解决方案来正确编译,因为模板模板确实让人头疼。


1

我的赌注是 MSVC 默默地吞噬了 const ,就像 const classes 一样。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接