Шаблон класса C , принимающий любой тип или нетип

#c #templates

#c #шаблоны

Вопрос:

Я вижу несколько похожих вопросов, но, похоже, они этого не понимают.

Я могу перегрузить функцию в шаблоне:

 template <typename T> void foo(); // Called as e.g., foo<int>();
template <std::size_t I> void foo(); // Called as e.g., foo<2>();
 

Есть ли способ сделать что-то подобное с классом, где я могу иметь либо MyClass<int> или MyClass<2> ?

Я не вижу способа сделать это. (Моя настоящая цель — иметь static constexpr экземпляр вызываемого объекта, который действует как std::get . В то std::get время как шаблон используется для его параметра «индексирование» и для типа аргумента, я бы хотел создать тот, который вызывается сам по себе, поэтому myns::get<2> и myns::get<int> оба являются вызываемыми, а при вызове действуют как std::get<2>(tup) и std::get<int>(tup) соответственно.

Наивно надеяться, что что-то подобное сработает, но auto это тип:

 template <auto IndOrType>
constexpr auto get = [](autoamp;amp; tup) {
    return std::get<IndOrType>(std::forward<decltype(tup)>(tup));
};
 

Я могу создать функцию получения, которая возвращает лямбда-выражение, но тогда она вызывается () как в myns::get<2>()(tup) or myns::get<int>()(tup) .

Ответ №1:

Вы могли бы специализировать класс, используя вспомогательный тип std::integral_constant<int,N> . Хотя, к сожалению, это не совсем позволяет MyClass<2> использовать синтаксис:

 #include <type_traits>

template<typename T>
class MyClass
{
};

template<int N>
using ic = std::integral_constant<int,N>;

template<int N>
class MyClass<ic<N>>
{

};

int main()
{
    MyClass<int> a;
    MyClass<ic<2>> b;
}
 

https://godbolt.org/z/84xoE1Yd4

Комментарии:

1. Правильно. Если бы только был способ сделать 2 неявное преобразование в ic<2> в этом контексте…

2. Да, я надеялся, что он может автоматически соответствовать специализации, но, увы.

3. Кстати, я не совсем уверен в вашем предполагаемом варианте использования. Но, возможно, не может работать перегруженная функция makeMyClass ? Вместо того, чтобы напрямую называть тип, позвольте перегруженной функции выполнять специализацию для любой версии MyClass .

4. Я действительно просто надеялся синтаксически сделать auto f = get<X>; f(t); и заставить это действовать std::get<X>(t); , что кажется естественным. Это кажется таким простым, но для этого я обнаружил, что чувствую, что это возможно, поэтому я решил, что это хороший вопрос для SO.

5. Кажется, что шаблоны функций — это единственное, что может быть перегружено в главном параметре шаблона, поэтому в конечном итоге перегрузка может оказаться невозможной.