Выведите тип параметра шаблона ссылки - PullRequest
3 голосов
/ 27 марта 2020

Если имеется

template <class T>
class A{};

// global namespace, static storage duration
static constexpr A<int> a;

, можно ли вывести тип A<int>, передав a в качестве параметра эталонного шаблона, например:

// This question asks to make the syntax in the following line compile:
static_assert(std::is_same<A<int>, typename GetReferenceType<a>::type>::value, "");
// I am aware the next line works, but it's not what I am looking for in this question
static_assert(std::is_same<A<int>, decltype(a)>::value, "");

// This is pseudo code of how this could work in theory
template <const T& RefT, class T> // I know this does not compile, but this shows what I want
struct GetReferenceType{          // which is automatically deduce type `T` without having to 
  using type = T;                 // write it out
};

Ответ который объясняет, почему это невозможно в C ++, приветствуется как решение для компиляции этого синтаксиса :) Я в основном спрашиваю из любопытства, поскольку в принципе все остальное можно вывести в шаблонах, но, очевидно, не в ссылочных типах.

Это также должно работать, но не удовлетворяет вышеуказанному синтаксическому требованию:

template <class T>
constexpr auto GetReferenceTypeFunc(const T& t) -> T;

static_assert(std::is_same<A<int>, decltype(GetReferenceTypeFunc(a))>::value, "");

Почему я хочу это сделать

Я стремлюсь к самому краткому синтаксис. Несмотря на то, что Instantiate<decltype(a)> работает, он не имеет высокого рейтинга по шкале краткости, особенно если возможен такой синтаксис, как Instantiate<a>.

Представьте себе, a не имеет короткого типа A<int>, а вместо этого что-то вроде A<OmgWhyIsThisTypeNameSoLong>.

Затем, если вы хотите создать экземпляр типа с помощью A<OmgWhyIsThisTypeNameSoLong>, вам нужно написать:

Instantiate<A<OmgWhyIsThisTypeNameSoLong>>;

Так уж получилось, что у нас уже есть глобальный объект a, поэтому было бы неплохо не писать этот длинный тип, а вместо этого Instantiate<a>.

Конечно, есть возможность создать псевдоним using AOmg = A<OmgWhyIsThisTypeNameSoLong>, но я бы очень хотел обойтись рассылка спама в пространстве имен с другим именем, очень похожим на A.

1 Ответ

2 голосов
/ 27 марта 2020

В C ++ 20 вы можете сделать:

template <auto V>
struct GetReferenceType
{
    using type = std::decay_t<decltype(V)>;  
};

static_assert(std::is_same<A<int>, GetReferenceType<a>::type>::value);

, но decltype кажется достаточным.

Демо

// Я хочу не только вывести A<int>, но и int

Так что вам, вероятно, нужна такая черта, как:

template <typename> struct t_parameter;

template <template <typename > class C, typename T> struct t_parameter<C<T>>
{
    using type = T;    
};

, но простой альтернативой является добавление информации непосредственно в A:

template <class T>
class A{
    using value_type = T;
};
...