Funkcja operująca na wektorze - template i iteratory

0

Cześć!

Usiłuję napisać funkcję która przeprowadzi mi na wektorze( lub jego fragmencie) pewną operacje.
Dla całego wektora:

    template<typename _Up>
    _Up rms2(const vector<_Up> &value){
        _Up sum = 0;
        for(typename vector<_Up>::const_iterator it = value.begin(); it != value.end(); ++it)
            sum += *it * *it;
        return sqrt(sum/2);
    }

Oraz podając tylko iteratory:

    template<typename _InputIterator>
    ??? rms2(_InputIterator __first, _InputIterator __last){
        typedef typename std::__is_integer<_InputIterator>::__type _Integral;
        ??? sum = 0;
        /* for itp - nie ma problemu */
        return sqrt(sum/2);
    }

Co wpisać w miejsce ??? - jak dostać się to typu wartości iterowanej?

2

auto i decltype odpowiednio.

Swoją drogą:

  1. co to za dziwne traity? #include <type_traits>
  2. _X gdzie X to wielka litera i __ są zarejestrowane dla implementacji, nie masz prawa nazywać tak swoich zmiennych (ani identyfikatorów w ogóle)

W ogóle, ja to bym napisał tak:

template<typename It1, typename It2>
auto rms2(It1 b, It2 e){
	auto sum = std::accumulate(b, e, decltype(*b){}, [](auto const& total, auto const& el){
		return total + el * el;
	});
	return sqrt(sum/2);
}

template<typename Container>
auto rms2(Container&& c){
	using std::begin;
	using std::end;
	return rms2(begin(c), end(c));
}

Nie ma tu co prawda ograniczenia do wektora, ale można to dodać.

0

Dzięki, a jak to zrobić bez używania auto?

0

Jesteś ograniczony do C++11 czy C++03?

0
kq napisał(a):

Jesteś ograniczony do C++11 czy C++03?

Wersja C++03, nie mam funkcji lambda i auto.
kq - Bardzo ciekawie piszesz kod. Można się bardzo dużo nauczyć. Z tego powodu bardzo Ci dziękuję.
Mogę prosić, abyś napisał taką funkcję (profesjonalnie) dla C++03?

0

Może coś takiego? Powinno się kompilować z C++03:

template<typename T>
struct Functor
{
	T operator()(T const& total, T const& el){
		return total + el * el;
	}
};

template<typename It1, typename It2>
typename std::iterator_traits<It1>::value_type
rms2(It1 b, It2 e){
	typedef typename std::iterator_traits<It1>::value_type value_type;
	value_type sum = std::accumulate(b, e, value_type(), Functor<value_type>());
	return sqrt(sum/2);
}

template<typename Container>
typename Container::value_type
rms2(Container const& c){
	return rms2(c.begin(), c.end());
}

http://melpon.org/wandbox/permlink/VzJkUIimYNL6jMaI

0

Już analizuję, póki co wrzucam to co naklepałem przez ten czas:

template<typename InputIterator>
typename std::iterator_traits<InputIterator>::value_type rms2(InputIterator first, InputIterator last){
    typename std::iterator_traits<InputIterator>::value_type total = 0;
    for(; first != last; ++first)
        total += *first * *first;
    return sqrt(total/2);
}

Mile widziane uwagi do tego co napisałem :)

0

W sumie jedyne co zrobiłeś to użyłeś pętli ręcznie zamiast algorytmu, ale w C++03 to jest imo wybaczalne (szczególnie jak porównasz do mojego kodu wyżej).

Mimo wszystko bardzo polecam zapoznanie się z https://channel9.msdn.com/Events/GoingNative/2013/Cpp-Seasoning

0

Ok, chętnie się zapoznam.
Wykorzystałem trochę kodu od "MarekR22" i zostawiam to w takiej formie:

    template<typename T>
    T sum_pow(T const& total, T const& value){
        return total + value * value;
    }

    template<typename InputIterator>
    typename std::iterator_traits<InputIterator>::value_type
    rms(InputIterator first, InputIterator last){
        using value_type = typename std::iterator_traits<InputIterator>::value_type;
        value_type total = std::accumulate(first, last, value_type(), sum_pow<value_type>);
        return sqrt(total/2);
    }

    template<typename T>
    T rms(const vector<T>& value){
        return rms(value.begin(), value.end());
    }

Dzięki!

1 użytkowników online, w tym zalogowanych: 0, gości: 1