如何访问未命名的命名空间中的隐藏模板?

时间:2010-05-28 21:29:28

标签: c++ templates names

这是一个棘手的情况,我想知道有什么方法可以解决它

namespace {
  template <class T> 
  struct Template { /* ... */ }; 
}

typedef Template<int> Template;

遗憾的是,Template typedef会干扰未命名的命名空间中的Template模板。当您尝试在全局范围内执行Template<float>时,编译器会在模板名称和typedef名称之间引发歧义错误。

您无法控制模板名称或typedef-name。现在我想知道是否可以:

  • 在全局命名空间中创建typedefed类型Template(即Template<int>)的对象。
  • 在全局命名空间中创建类型为Template<float>的对象。

允许向未命名的命名空间添加任何内容。一切都应该在全局命名空间中完成。

这是出于好奇,因为我想知道解决这种模棱两可的技巧。这不是我在日常节目中遇到的实际问题。

4 个答案:

答案 0 :(得分:1)

使用C ++ 0x:

namespace {
  template<class T> struct Template { };
}
typedef Template<int> Template;

#include<iostream>

template<typename T> 
void PrintType() { 
    std::cout << __PRETTY_FUNCTION__ << std::endl; 
}

template<typename FullType, typename NewParameter>
class Rebind {
  template<template<class> class Template, typename OldParameter>
  static Template<NewParameter> function(Template<OldParameter>);

public:
  typedef decltype(function(FullType())) NewType;
};

int main()
{
  PrintType< ::Template>();
  PrintType<Rebind< ::Template, float>::NewType>();
  return 0;
}

使用gcc45产生

void PrintType() [with T = <unnamed>::Template<int>]
void PrintType() [with T = <unnamed>::Template<float>]

显然它与Cormeau编译,但我只能访问他们的在线测试,所以我只是假设它按预期运行而停滞不前。

我无法想出任何方法直接将实际类型传递给结构并使其降级为模板类型,但编译器在必须猜测函数参数时没有问题。也许这可以在C ++ 03中使用boost::result_of而不是decltype,但我以前从未使用它,所以我想我会坚持我所知道的。

请注意main内的间距。由于Rebind<::Template, float>::NewType是有向图,<:被解析器吞噬。我认为它变成了Rebind[:Template, float>::NewType。因此::Template之前的空间至关重要。

顺便说一句,我不知道嵌套模板参数不能使用typename [template<template<typename> class T>而不是template<template<typename> typename T>]。我想我每次尝试记住构造的语法时都要重新学习。

答案 1 :(得分:0)

我知道这有点破坏了你的观点,但我认为主要的伎俩是避免像瘟疫这样的事情。

答案 2 :(得分:0)

可以通过明确命名空间来访问全局typedefed模板,即

::Template a

是来自匿名命名空间的Template<int>。不确定您是否可以获得Template<float>

令人惊讶Clang的C ++编译器可以满足以下要求,可能不是标准行为:

#include <iostream>
namespace {
    template <class T>
        struct Template {T value;};}
typedef Template<int> Template;

int main(){    
    ::Template a;
    Template<float> b;
    a.value = 6;
    b.value = 3.14;
    std::cout<<a.value<<" "<<b.value<<"\n";
}

答案 3 :(得分:-1)

免责声明:我不知道你为什么要这样做,并且可能会对那些做过的人严厉说话。

namespace
{
   template <typename T> class Template { };
}

typedef Template<int> IntTemplate;
typedef Template<float> FloatTemplate;
typedef IntTemplate Template;

int main() {
    ::Template t;
    FloatTemplate ft;
}