Как мне получить этот шаблонный класс для компиляции для классов и примитивных типов? - PullRequest
4 голосов
/ 30 октября 2011

Как мне получить следующий код для компиляции?

Я понимаю, что компилятор недоволен V<double>, потому что он пытается скомпилировать мой typedef для GetterFn, но я бы хотел, чтобы GetterFn и GetCalc() были доступными для классов, но игнорируются примитивные типы.

Как мне перекодировать этот класс?

#include <vector>

using namespace std;

class Bar
{
    public:
        float getMyFloat() const { return 42.5; }
};

template< typename T >
class V
{
    public:
        typedef float (T::*GetterFn)() const;
        void getCalc( std::vector<double>& vec, GetterFn fn ) const
        {
            vec.clear();
            for ( size_t i=0; i<m_v.size(); ++i )
                vec.push_back( m_v[ i ].*(fn)() );
        }

    private:
        vector<T> m_v;
};

int main(int argc, char** argv)
{
    V<Bar>    vb;  // ok
    V<double> vd;  // compiler not happy
}

Ответы [ 3 ]

3 голосов
/ 30 октября 2011

Немного странный ответ Альфа - действительно самый простой способ. Вместо того, чтобы GetterFn был указателем на функцию-член, просто используйте перегруженную свободную функцию, чтобы получить значение:

void getCalc( std::vector<double>& vec) const
{
    vec.clear();
    for ( size_t i=0; i<m_v.size(); ++i )
        vec.push_back( get_value(m_v[ i ]) );
}

и затем просто перегрузить get_value соответственно:

double get_value(double value) { return value; }

double get_value(Bar value) { return value.getMyFloat(); }

Конечно, рекомендуется более описательное имя, чем get_value.

1 голос
/ 30 октября 2011

Довольно сложно предложить полное решение, не зная, что вы хотите сделать для основных типов. Однако в глубине души я предлагаю вам использовать черту типа std::is_fundamental.

Если вы хотите, чтобы целые коллекции функций-членов существовали только условно, возможно, одна из них заключается в том, чтобы объединить их в класс помощника-члена:

#include <vector>
#include <type_traits>
#include <cstddef>

class Bar
{
public:
  float getMyFloat() const { return 42.5; }
};

template< typename T >
class V
{
private:

  static const bool m_primitive = std::is_fundamental<T>::value; // convenience

  template <bool B, typename U> struct Helper;

  template <typename U> struct Helper<false, U>
  {
    typedef float (T::*GetterFnType)() const;
    void getCalc(std::vector<double> & v1, std::vector<U> const & v2, GetterFnType f)
    {
      v1.clear();
      for (std::size_t i = 0; i < v2.size(); ++i)
        v1.push_back((v2[i].*f)());
    }
  };

public:

  // use Helper<m_primitive, T>::GetterFn and Helper<m_primitive, T>::getCalc() here

private:
  std::vector<T> m_v;
};

int main(int argc, char** argv)
{
  V<Bar>    vb;  // ok
  V<double> vd;  // compiler also happy
}

Вам, вероятно, также придется сделать std::enable_if в реальной реализации. Если вы разместите более подробную информацию, мы можем уточнить.

Если вы открыты для более широкой редизайн, ответ Конрада кажется, что конечный результат будет несколько чище и проще, но опять же я все в пользу извилистого шаблона voodoo: -)

1 голос
/ 30 октября 2011

A double не может иметь функцию-член.Ergo, используйте функцию, не являющуюся членом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...