У меня есть такой шаблон в C ++
template<typename T, T* P> struct Ptr {};
так что я могу использовать это как так:
const int i = 0;
Ptr<int, &i> ptr;
или же
Ptr<decltype(i), &i> ptr;
Но я не хочу указывать тип int
или личность i
дважды, я хочу использовать только
Ptr<&i> ptr;
и пусть компилятор выяснит int
введите часть сама.
Как я могу объявить мой шаблон для этого?
Я читал этот вопрос, но в ответе используются макросы, это нехорошо:
шаблон шаблона с ++?
я могу сделать это просто по шаблону без макросов? Я использую Visual C ++ 2013.
ОБНОВИТЬ
C ++ 17 представил «P0127R2 Объявление не типовых параметров шаблона с автоmsgstr «, позволяющий объявить нетиповые параметры шаблона с auto
в качестве заполнителя для фактического типа:
template <auto P> struct Ptr {};
То есть, P
является нетиповым параметром шаблона. Его тип может быть выведен с decltype(P)
,
auto
На шаблон списка параметров распространяются общеизвестные правила вычета и частичного упорядочения. В вашем случае тип может быть ограничен, чтобы принимать только указатели:
template <auto* P> struct Ptr {};
Обратите внимание, что использование синтаксиса auto
достаточно даже для более детальной проверки, например:
template <typename F>
struct FunctionBase;
template <typename R, typename... Args>
struct FunctionBase<R(*)(Args...)> {};
template <auto F>
struct Function : FunctionBase<decltype(F)> {};
Также возможно использовать выведенный тип как ограничение для других параметров шаблона:
template <auto I, decltype(I)... Is>
struct List {};
Старый ответ
Поскольку вы спрашиваете о чистом решении на основе шаблонов классов без помощи определений макросов, ответ прост: как сейчас (декабрь 2014 г., C ++ 14) это невозможно.
Эта проблема уже была определена Комитетом по стандартизации WG21 C ++ как необходимость, и существует несколько предложений, позволяющих шаблонам автоматически определять тип аргументов шаблонных типов.
Ближайший N3601 Неявные параметры шаблона:
Неявные параметры шаблона
Целью этого примера является устранение необходимости в избыточном
template<typename T, T t>
идиома. Эта идиома широко используется, более 100 тысяч просмотров в Google.Цель состоит в том, чтобы иметь возможность заменить объявление шаблона как
template<typename T, T t> struct C;
с другой декларацией, чтобы мы могли создать экземпляр шаблона, какC<&X::f>
вместо того, чтобы сказатьC<decltype(&X::f), &X::f>
,Основная идея заключается в том, чтобы уметь
[…]template<using typename T, T t> struct C {/* ... */};
указать, чтоT
должно быть выведено. Для более подробного описания рассмотрим несколько расширенных примеров шаблонных классов и функций.Основная идея заключается в том, что передача типа второго параметра шаблона является избыточной информацией, поскольку ее можно вывести, используя вывод обычного типа из параметра второго типа. Имея это в виду, мы предлагаем, чтобы предварительный поиск параметра шаблона с использованием указывает, что он не должен передаваться явно в качестве аргумента шаблона, а вместо этого будет выводиться из последующих нетипизированных аргументов шаблона. Это сразу позволяет нам улучшить удобство использования
describe_field
следующее.template<using typename T, T t> struct describe_field { /* ... */ }; /* ... */ cout << describe_field<&A::f>::name; // OK. T is void(A::*)(int) cout << describe_field<&A::g>::arity; // OK. T is double(A::*)(size_t)
Аналогичное предложение включено в N3405 Шаблонные лакомые кусочки:
Т на двоих
Мотивирующим примером является предполагаемая черта типа отражения, дающая свойства члена класса.
struct A { void f(int i); double g(size_t s); }; /* ... */ cout << describe<&A::f>::name; // Prints "f"cout << describe<&A::g>::arity; // prints 1
Вопрос в том «Как должно выглядеть объявление описания?» Так как он принимает не шаблонный параметр типа, нам нужно указать тип параметра, используя знакомый (100 000 просмотров в Google)
“template<class T, T t>”
идиома[…]template<typename T, T t> struct describe;
Наша ключевая идея заключается в том, что передача типа второго параметра шаблона является (почти всегда) избыточной информацией, поскольку ее можно вывести, используя вывод обычного типа из параметра второго типа. Имея это в виду, мы предлагаем разрешить
describe
быть объявленным следующим образом.template<typename T t> struct describe; /* ... */ cout << describe<&A::f>::name; // OK. T is void(A::*)(int) cout << describe<&A::g>::arity; // OK. T is double(A::*)(size_t)
Текущий статус обоих предложений можно отслеживать в разделе РГЭ, выпуск 9.
Есть некоторые другие обсуждение предлагая альтернативный синтаксис с auto
:
template <auto T> struct describe;