Как получить доступ к скрытому шаблону в безымянном пространстве имен? - PullRequest
4 голосов
/ 29 мая 2010

Вот сложная ситуация, и мне интересно, как ее можно решить

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

typedef Template<int> Template;

К сожалению, определение типа Template мешает шаблону Template в безымянном пространстве имен. Когда вы пытаетесь сделать Template<float> в глобальной области видимости, компилятор вызывает ошибку неоднозначности между именем шаблона и именем typedef.

Вы не можете контролировать ни имя шаблона, ни имя типа определения. Теперь я хочу знать, возможно ли:

  • Создайте объект типа typedefed Template (т.е. Template<int>) в глобальном пространстве имен.
  • Создать объект типа Template<float> в глобальном пространстве имен.

Вы не можете добавлять что-либо в безымянное пространство имен. Все должно быть сделано в глобальном пространстве имен.

Это из любопытства, потому что мне было интересно, какие хитрости существуют для решения такой двусмысленности. Это не практическая проблема, с которой я сталкиваюсь во время ежедневного программирования.

Ответы [ 4 ]

1 голос
/ 29 мая 2010

Использование 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 жизненно важно.

Кроме того, я понятия не имел, что вложенные параметры шаблона не могут использовать имя типа [template<template<typename> class T> вместо template<template<typename> typename T>]. Я думаю, что переучиваю это каждый раз, когда пытаюсь запомнить синтаксис конструкции.

0 голосов
/ 29 мая 2010

Можно получить доступ к глобальному шаблону определения типа, явно указав пространство имен, т.е.

::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";
}
0 голосов
/ 29 мая 2010

отказ от ответственности: я не знаю, почему вы хотите это сделать, и, вероятно, строго поговорите с кем-то, кто это сделал.

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

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

int main() {
    ::Template t;
    FloatTemplate ft;
}
0 голосов
/ 29 мая 2010

Я знаю, что это несколько портит вашу точку зрения, но я действительно считаю, что главная хитрость заключается в том, чтобы избежать чего-то подобного, например чумы.

...