Портативный тип имени с внешней связью

В статье доктора Добба Переносной оператор typeof говорится

Но вы не можете использовать шаблон класса для извлечения типа из выражения, как вы можете использовать шаблоны функций или перегрузку. (Если выражение представляет собой имя с внешней связью, можно реализовать typeof с шаблонами классов, используя нетиповой параметр шаблона, но это не очень полезно.)

Верно ли выделенное жирным шрифтом предложение в скобках? И если да, то как можно использовать нетиповой параметр шаблона для поиска типа выражения с внешней связью?


person qbt937    schedule 25.12.2014    source источник
comment
Вот моя попытка - она ​​не работает, поэтому я публикую ее как комментарий. Проблема в проблеме курицы и яйца. Теперь, если бы вы могли каким-то образом отложить объявление параметра типа или могли бы иметь template<T* val>, это могло бы сработать.   -  person milleniumbug    schedule 25.12.2014
comment
@milleniumbug - очень плохо, что С++ требует объявления шаблона, прежде чем его можно будет специализировать. В противном случае это может работать как template<typename T, T* V> struct<V> { typedef T type };.   -  person qbt937    schedule 26.12.2014
comment
Я не думаю, что автор этой статьи доктора Добба думал, что он может взять тип выражения, который пытался сделать @milleniumbug, потому что это не объясняет необходимость того, чтобы это была внешняя ссылка.   -  person qbt937    schedule 26.12.2014
comment
@ qbt937 На самом деле, внешняя связь является причиной, по которой я попытался, см. этот ответ с соответствующей стандартной цитатой. Хотя этот конкретный вопрос касается С++ 11, насколько я помню, проблема связи актуальна и для С++ 03.   -  person milleniumbug    schedule 26.12.2014


Ответы (2)


В C++03 невозможно реализовать typeof без использования sizeof. Ближайшая полезная альтернатива — извлечь тип с помощью шаблона функции, который возвращает желаемый тип.

template<typename T>
struct Type
{
};

template<typename T>
Type<T> makeType(T)
{
    return Type<T>();
}


int main()
{
    int i;

    makeType(2 + 2); // Type<int>
    makeType(&i); // Type<int*>
}

В следующем методе используются шаблоны функций в C++03 для извлечения типа и значения любого выражения, которое можно использовать в аргументе шаблона.

template<typename T, T value>
struct NonType
{
};


template<typename T>
struct Type
{
    template<T value>
    static NonType<T, value>
        makeNonType()
    {
        return NonType<T, value>();
    }
};

template<typename T>
Type<T> makeType(T)
{
    return Type<T>();
}


#define MAKE_NONTYPE(e) makeType(e).makeNonType<e>()

int i;

int main()
{
    MAKE_NONTYPE(2 + 2); // NonType<int, 4>
    MAKE_NONTYPE(&i); // NonType<int*, i>
}

В следующем ответе показано практическое использование этого метода для извлечения типа и значения указателя на выражение функции-члена: -work-on-both-member-and-non-member-functions/17237671#17237671">Как разрешить шаблонному функтору работать как с функциями-членами, так и с функциями, не являющимися членами

person willj    schedule 26.12.2014
comment
Вы действительно получаете выражение типа NonType<T, v>, но поскольку у вас нет typeof или decltype, вы все равно не можете использовать его для ссылки на этот тип. Извините, но я не думаю, что это полезно здесь. - person ; 26.12.2014
comment
Это не typeof или decltype, но это полезная альтернатива для решения подмножества проблем, к которым они относятся. - person willj; 26.12.2014
comment
@qbt937 ... для чего? Это не обходной путь AFAICS. - person Columbo; 26.12.2014

В C++03 это не работает - подход на самом деле бессмысленный, я предполагаю, что автор не до конца продумал эту идею.

Однако с неявными параметрами шаблона (как предложено для C++1Z) это действительно может работать:

template <using typename T, T&> struct infer {using type = T;};

int a;
infer<a>::type // int

Это все еще не определяет, является ли a ссылкой.

person Columbo    schedule 26.12.2014