Ограничьте шаблонную функцию

Другое событие NullPointerException возникает, когда объявляется массив объектов, а затем сразу же пытается разыменовать его внутри.

String[] phrases = new String[10];
String keyPhrase = "Bird";
for(String phrase : phrases) {
    System.out.println(phrase.equals(keyPhrase));
}

Этот конкретный NPE можно избежать, если порядок сравнения отменяется ; а именно, использовать .equals для гарантированного непустого объекта.

Все элементы внутри массива инициализируются их общим начальным значением ; для любого типа массива объектов, это означает, что все элементы null.

Вы должны инициализировать элементы в массиве перед доступом или разыменованием их.

String[] phrases = new String[] {"The bird", "A bird", "My bird", "Bird"};
String keyPhrase = "Bird";
for(String phrase : phrases) {
    System.out.println(phrase.equals(keyPhrase));
}

16
задан Marc 5 November 2012 в 16:06
поделиться

7 ответов

Единственный способ ограничить шаблон состоит в том, чтобы сделать его так, чтобы это использовало что-то от типов, которые Вы хотите, что другие типы не имеют.

Так, Вы создаете с интервалом, используете + и + =, вызываете конструктора копии, и т.д.

Какой-либо тип, который имеет все их, будет работать с Вашей функцией - так, если я создам новый тип, который имеет эти функции, Ваша функция будет работать над ним - который является большим, не так ли?

, Если Вы хотите ограничить его больше, используйте больше функций, которые только определяются для типа, который Вы хотите.

Другой способ реализовать это путем создания шаблона черт - что-то вроде этого

template<class T>
SumTraits
{
public:
  const static bool canUseSum = false;
}

, И затем специализируйте его для классов, Вы хотите быть в порядке:

template<>
class SumTraits<int>
{
  public:
    const static bool canUseSum = true;
};

Тогда в Вашем коде, можно записать

if (!SumTraits<T>::canUseSum) {
   // throw something here
}

редактирование: как упомянуто в комментариях, можно использовать BOOST_STATIC_ASSERT для создания его проверкой времени компиляции вместо во время выполнения

18
ответ дан 30 November 2019 в 15:16
поделиться

Это возможно при помощи SFINAE, и сделанный легче при помощи помощников или от Повышения или от C++ 11

Повышение:

#include <vector>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_arithmetic.hpp>

template<typename T> 
    typename boost::enable_if<typename boost::is_arithmetic<T>::type, T>::type 
        sum(const std::vector<T>& vec)
{
  typedef typename std::vector<T>::size_type size_type;
  T result;
  size_type size = vec.size();
  for(size_type i = 0; i < size; i++)
  {
    result += vec[i];
  }

  return result;
}

C++ 11:

#include <vector>
#include <type_traits>

template<typename T> 
    typename std::enable_if<std::is_arithmetic<T>::value, T>::type 
        sum(const std::vector<T>& vec)
{
  T result;
  for (auto item : vec)
    result += item;
  return result;
}
20
ответ дан 30 November 2019 в 15:16
поделиться

Можно сделать что-то вроде этого:

template <class T>
class NumbersOnly
{
private:
    void ValidateType( int    &i ) const {}
    void ValidateType( long   &l ) const {}
    void ValidateType( double &d ) const {}
    void ValidateType( float  &f ) const {}

public:
    NumbersOnly()
    {
       T valid;
       ValidateType( valid );
    };
};

Вы получите ошибку, при попытке создать NumbersOnly, который не имеет перегрузки ValidateType:

NumbersOnly<int> justFine;
NumbersOnly<SomeClass> noDeal;
19
ответ дан 30 November 2019 в 15:16
поделиться

Именно так Вы делаете это.

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

сообщение об ошибке не интуитивно, если Вы не переименовываете IsNumber класс к чему-то, что походит на сообщение об ошибке.

#include <vector>
#include <iostream>

using namespace std;

template<class T> struct IsNumber{ 
 private:
 IsNumber(){}
 };

 template<> struct IsNumber<float>{
   IsNumber(){};
 };

 template<> struct IsNumber<double>{
   IsNumber(){};
 };

 template<> struct IsNumber<int>{
   IsNumber(){};
 };

template <typename T>
T sum(vector<T>& a)
{
 IsNumber<T> test;
 T result = 0;
 int size = a.size();
 for(int i = 0; i < size; i++)
 {
  result += a[i];
 }

 return result;
}




int main()
{
 vector<int> int_values;
 int_values.push_back(2);
 int_values.push_back(3);
 cout << "Integer: " << sum(int_values) << endl;

 vector<double> double_values;
 double_values.push_back(1.5);
 double_values.push_back(2.1);
 cout << "Double: " << sum(double_values);

 return 0;
}
3
ответ дан 30 November 2019 в 15:16
поделиться

Почему Вы хотели бы ограничить типы в этом случае? Шаблоны позволяют "статический утиный ввод", таким образом, что-либо позволенное тем, что Ваш sum в этом случае должна быть позволена функция. А именно, единственная операция, требуемая T, является добавлять-присвоением и инициализацией 0, таким образом, любой тип, который поддерживает те две операции, работал бы. Это - красота шаблонов.

(При изменении инициализатора на T result = T(); и т.п., тогда это работало бы и на числа и на строки, также.)

1
ответ дан 30 November 2019 в 15:16
поделиться

Вы могли изучить черты типа (используйте повышение, ожидайте C++ 0x или создайте Ваше собственное).

я нашел следующий Google: http://artins.org/ben/programming/mactechgrp-artin-cpp-type-traits.pdf

1
ответ дан 30 November 2019 в 15:16
поделиться

Действительно, нет никакой потребности сделать его более строгим. Взгляните на строковую версию (использующий стиль конструктора по умолчанию, рекомендуемый Chris Jester-Young) здесь ...

Заботятся также для переполнения - Вам, возможно, понадобился бы больший тип, чтобы содержать промежуточные результаты (или произвести результаты). Добро пожаловать в область метапрограммирования, тогда:)

1
ответ дан 30 November 2019 в 15:16
поделиться
Другие вопросы по тегам:

Похожие вопросы: