Подтвердить что ты не робот

Как сделать, если какой-либо другой тип типа в шаблоне С++?

// template specialization
#include <iostream>
using namespace std;

// class template:
template <class T>
class mycontainer {
    T element;
  public:
    mycontainer (T arg) {element=arg;}
    T increase () {

    //if(T.type==int)//how to do this or something similar?
    //do this if an int
    return ++element;

    //if(T.type==char)
     //if ((element>='a')&&(element<='z'))
      //element+='A'-'a';
      //return element;

    }
};

Я знаю, как написать специализацию шаблона и сделать отдельный класс класса только для типа char.

Но что, если я хочу обрабатывать все только в одном блоке кода?

Как проверить, является ли T int или char?

4b9b3361

Ответ 1

Вы можете использовать typeid:

if (typeid(T) == typeid(int))

Или вы можете использовать черту типа std::is_same:

if (std::is_same<T, int>::value)

Ответ 2

Что вы хотите, вероятно, что-то вроде время компиляции, если. К сожалению, С++ 11 не имеет встроенной поддержки такой конструкции языка.

Однако, если вы просто хотите проверить, идентичны ли два типа, черта типа std::is_same<> должна помочь вам:

#include <type_traits> // <== INCLUDE THIS STANDARD HEADER

// class template:
template <class T>
class mycontainer 
{
    T element;
public:
    mycontainer (T arg) {element=arg;}
    T increase () 
    {
        if (std::is_same<T, int>::value)   // <== THIS IS HOW YOU WOULD USE IT
            return ++element;

        if (std::is_same<T, char>::value)  // <== THIS IS HOW YOU WOULD USE IT
        {
            if ((element>='a') && (element<='z'))
                element+='A'-'a';
        }

        return element;
    }
};

Однако имейте в виду, что условие оценивается во время выполнения, хотя значение is_same<T, int>::value известно во время компиляции. Это означает, что и ветвь true и false оператора if должны компилировать!

Например, следующее не было бы законным:

if (std::is_same<T, int>::value)
{
    cout << element;
}
else if (std::is_same<T, my_class>::value)
{
    element->print();  // Would not compile when T is int!
}

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

Ответ 3

Как насчет простой перегрузки?

// in the private section
static int& do_increase(int& i){ return ++i; }
static char& do_increase(char& c){
  if(c >= 'a' && c <= 'z')
    c += 'A' - 'a';
  return c;
}
template<class U>
static U& do_increase(U& arg){
  // some default implementation?
  return arg;
}

(Обратите внимание, что стандарт не гарантирует алфавитный порядок для числовых значений char.)

Тогда просто назовите это в increase как return do_increase(element);.

Ответ 4

Вы можете использовать специальную спецификацию шаблона

#include <iostream>
using namespace std;

// class template:
template <class T>
class mycontainer {
    T element;
  public:
    mycontainer (T arg) {element=arg;}
    T increase();
};


template<>
int mycontainer<int>::increase(){
    return ++element;
}

template<>
char mycontainer<char>::increase(){
    if ((element>='a')&&(element<='z'))
       element+='A'-'a';
    return element;
}

int main(){
        mycontainer<int> A(10);
        mycontainer<char> B('x');

        cout << A.increase() <<endl;
        cout << B.increase() <<endl;
        return 0;
}

Ответ 5

Обычным решением здесь является пересылка на перегруженную функцию с дополнительным аргументом. Что-то вроде:

template <typename T>
class MyContainer
{
    T increase( int const* ) { /* special treatment for int */ }
    T increase( ... )        { /* default treatment         */ }
public:
    T increase()
    {
        return increase( (T const*)0 );
    }
};

С небольшим воображением вы можете придумать всевозможные различия. Если вы выполняете целевые функции с помощью дополнительных шаблонов аргументов, вы даже можете использовать SFINAE: дизайн фиктивный аргумент, чтобы смена типа шаблона не удалась, и функция не будет учитываться в наборе перегрузки. А также поскольку все функции являются встроенными, возможно, что не будет лишних накладных расходов при условии, что вы оптимизируете.

Ответ 6

Это соответствует ответам Andy Prowls, но все это делается во время компиляции с использованием минимального вспомогательного класса со специализацией.

В этом случае у вас есть помощник, который действительно выполняет специализацию, но вы также можете иметь вспомогательный класс, просто беря bool, а затем используйте что-то вроде std::is_same<T, int>::value для передачи этого значения в качестве параметра шаблона.

template <typename T>
struct myContainerHelper;
{
    // General Case
    static inline T increase(T element)
    {
        return ++element;
    }
};

template <>
struct myContainerHelper<char>
{
    // Specific case
    static inline char increase(char element)
    {
        if ((element>='a')&&(element<='z')) element+='A'-'a';
        return element;
    }
};

template <class T>
class mycontainer 
{
    T element;
public:
    mycontainer (T arg) {element=arg;}
    T increase () 
    {
        return myContainerHelper<T>::increase(element);
    }
};

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