我在g ++ 4.4和4.5上发现了一个奇怪的问题。我问过这个因为我认为我在代码中犯了一些愚蠢的错误。原帖是here但是对于后期完整性,我会在这里重新发布有问题的代码:
$ cat templatetemplate.cc
template <int i>
struct LabelTypeMap { typedef int type_t; };
template <bool>
struct Hold { typedef int type; };
template<typename Holder, template<typename Holder::type> class typeMap>
struct Whatever { };
template <bool Enable>
struct Now { typedef Whatever<Hold<ENABLE>, LabelTypeMap> concrete_t; };
Now<true>::concrete_t obj;
$ g++ -DENABLE=Enable -c templatetemplate.cc
templatetemplate.cc:11: error: type/value mismatch at argument 2 in template parameter list for ‘template<class Holder, template<typename Holder::type <anonymous> > class typeMap> struct Whatever’
templatetemplate.cc:11: error: expected a template of type ↵
‘template<typename Holder::type <anonymous> > class typeMap’, got ↵
‘template<int i> struct LabelTypeMap’
marcelo@macbookpro-1:~/play$
$ g++ -DENABLE=true -c templatetemplate.cc
(no error)
它似乎不是真正的程序员错误,虽然可能有可能我错过了模板模板参数解析的一些模糊规则。然而,我尝试将错误发布到ubuntu跟踪器(希望他们会解雇它或以其他方式向上游发送错误)
所以,只是为了检查这是否真的是一个错误,我得到了2003年标准的副本,我现在已经阅读了14.3.3节,但我觉得我一点也不想错过如果允许或禁止在示例代码中传递带参数的模板模板参数,则提示线索。我甚至不确定文件的这一部分是否提及有关此内容的任何内容
以下是我的问题:你知道这是指定的吗?
编辑:非常有趣的是,这个问题已经过了一个多星期没有回答:它让我相信ISO c ++标准没有指定我们是否可以使用以前的模板参数来指定后续模板参数的类型(at至少在所述形式中),这基本上留给实施者决定第二次编辑(2011年10月1日):人们,可能有些事情我们都缺少(或者许多高技能的编译器设计者都错了): 我用intel c ++编译器XE 12.0尝试了这个,我得到了这个:
$icpc ttemplatetemplate.cc -o ./x2test
templatetemplate.cc(12): error: class template "LabelTypeMap" is not compatible with template template parameter "typeMap"
struct Now { typedef Whatever<Hold<Enable>, LabelTypeMap> concrete_t; };
^
compilation aborted for templatetemplate.cc (code 2)
$ icpc --version
icpc (ICC) 12.0.0 20101116
Copyright (C) 1985-2010 Intel Corporation. All rights reserved.
答案 0 :(得分:1)
我在禁止它的标准中找不到任何内容,尽管我在Comeau中尝试了这个简单的代码(在我看来是对问题的简化):
template<int>
class A {};
template<class T, template<T> class U>
class B {};
B<int, A> b;
它会产生以下错误:
“ComeauTest.c”,第4行:错误: a 模板模板的参数 参数不能 取决于另一个模板参数的类型
我希望我能找到标准的哪一部分实际上禁止它......
答案 1 :(得分:1)
template <int i>
struct LabelTypeMap { typedef int type_t; };
template <bool>
struct Hold { typedef int type; };
template<typename Holder>
struct Whatever {
typedef typename Holder::type HT;
template <template <HT> class typeMap>
struct Whatever2 { };
};
template <bool Enable>
struct Now { typedef typename Whatever<Hold<Enable> >::Whatever2<LabelTypeMap> concrete_t; };
使用嵌套模板,我可以通过typename
引入typedef
。
答案 2 :(得分:0)
我怀疑这个奇怪的构造:template<typename Holder::type> class typeMap
应该是什么? typename Holder::type
位很奇怪;这应该是一个虚拟名称(标识符)。 Holder::type
甚至不是标识符。
答案 3 :(得分:-1)
这不是它应该是怎么回事?
这是因为LabelTypeMap本身就是一个模板(模板模板参数),因此需要指定一个类型。
template <bool Enable>
struct Now { typedef Whatever<Hold<ENABLE>, LabelTypeMap<ENABLE> > concrete_t; };