PDA

View Full Version : سوال: سربارگذاری (overloading) اپراتور پرانتز با n تا آرگومان



aliv.2022
چهارشنبه 05 آذر 1393, 18:38 عصر
سلام، میخواستم ببینم راهی هست که اپراتور () رو سربارگذاری کنیم واسه یه کلاس جوری که به جای تعداد مشخص، n تا آرگومان بشه توش نوشت؟ ببخشید اگر سوال واضح نیست اما استاد همینقدر توضیح داد O_o به عنوان راهنمایی هم porams رو تو c# گفت اما هرچی گشتم چیزی راجع به این هم نیافتم! البته شاید من غلظ نوشته باشم! چون با c# کار نکردم

shahmohammadi
چهارشنبه 05 آذر 1393, 18:48 عصر
سلام.
کاربردش چیه؟
به جای اینکه پرانتز رو آورلود کنیم که چند تا متغیر از یک کلاس رو بگیره، خب یه آرایه از اون کلاس رو میدیم. ارایه هم پویا باشه هر چن تا که بخواهید میشه.

aliv.2022
چهارشنبه 05 آذر 1393, 20:24 عصر
آره خب خیلی راه هست! اما اینو خواسته ازمون دیگه! اما در کل فک میکنم منظور اینه که چطور تابعی بنویسیم که هر چندتا بخوایم آرگومان بگیره! چون خود operator() تابعه دیگه در واقع!

omid_kma
چهارشنبه 05 آذر 1393, 20:31 عصر
به این شکل مثلا

#include <iostream>
#include <algorithm>
#include <vector>


class A
{
public:
template<class... Args>
void operator()(const Args&... args)
{
print(args...);
}
private:
template<class T,class... Args>
void print(const T& input,const Args&... args)
{
std::cout << input<<'\n';
print(args...);
}
template<class T>
void print(const T& input)
{
std::cout << input<<'\n';
}
};
int main()
{
A a;


a(1, 2, 'q', "test",5.64);
}

aliv.2022
چهارشنبه 05 آذر 1393, 22:01 عصر
راجع به
... Args
و
Args&... args
و
args...
یکم توضیح میدی؟

omid_kma
چهارشنبه 05 آذر 1393, 22:16 عصر
این روش برای تعریف variadic templae ها هست
قبل از c++11 مجبور بودیم ورودی های template امون محدود باشه ولی با استفاده از این روش جدید میشه تعداد نامحدودی نوع رو دریافت کرد .
برای تعریف variadic template به این شکل عمل می کنیم :
template <class...T
حالا T میتونه بجای تعداد نامحدودی پارامتر مورد استفاده قرار بگیره
هر جا هم که خواستید از T شی بسازین یا از شی ساخته شده استفاده کنید بعداز اسم متغیر باید از ...استفاده کنید تا کامپایلر بتونه تشخیص بده از variadic template استفاده کردین.
2 تابع print هم برای نوشتن مقادیر ورودی به شکل باز گشتی استفاده میشن .
داخل این لینک هم داخل پست آخر توضیحاتی هست : ویژگی های c++11 (http://www.7khatcode.com/index.php?qa=3180&qa_1=%D9%88%DB%8C%DA%98%DA%AF%DB%8C-%D9%87%D8%A7%DB%8C-c-11)

aliv.2022
چهارشنبه 05 آذر 1393, 22:42 عصر
تشکر فراوان! :)

iut.ali
چهارشنبه 05 آذر 1393, 22:59 عصر
از initializer_list هم میتونی استفاده کنی واسه فرستادن تعداد نامشخصی داده البته مثه template ها نیس و باید همون اول تو تابعت نوعش رو مشخص کنی

rahnema1
پنج شنبه 06 آذر 1393, 00:20 صبح
سلام
مطالب به خوبی توضیح داده شد. من هم مشتاق شدم یه نمونه دیگه بذارم. مثلا می خواهیم مقادیر یک آرایه با اندیسهایی که در پرانتز تعیین می کنیم استخراج کنیم

#include <vector>
#include <iostream>
using namespace std;
class MyArray
{
private:
vector<int> vec;
vector<int> vectemp;

public:
MyArray(vector<int> _v): vec(_v) {};

MyArray & operator()(int index)
{
vectemp.push_back(vec[index]);
return *this;
}
template <class ... T>
MyArray & operator()(int index,T ... indexes)
{
operator()(index);
operator()(indexes...);
return *this;
}

MyArray extract()
{
MyArray m(vectemp);
vectemp = vector<int>();
return m;
}
friend ostream& operator<<(ostream& stream, MyArray m)
{
for(auto && v: m.vec)
stream << v << endl;
return stream;
}
};
int main()
{
MyArray my1({23 ,44 ,67,24,89});
cout << my1(3,2,4,0,1,3).extract();
cout << "==="<<endl;
cout << MyArray({23 ,44 ,67,24,89})(3,2,4,0,1,3).extract();
cout << "==="<<endl;
cout << MyArray({23 ,44 ,67,24,89})(3,2,4,0,1,3).extract()(0,1).extract();
}

omid_kma
پنج شنبه 06 آذر 1393, 09:28 صبح
سلام
مطالب به خوبی توضیح داده شد. من هم مشتاق شدم یه نمونه دیگه بذارم. مثلا می خواهیم مقادیر یک آرایه با اندیسهایی که در پرانتز تعیین می کنیم استخراج کنیم

البته من دسترسی با index رو به شکل زیر بیشتر ترجیح میدم :)
(نهایت سو استفاده از سینتکس ++C :لبخند: )

#include <type_traits>
#include <vector>
#include <tuple>
#include <iostream>


// indices are a classic
template< std::size_t... Ns >
struct indices
{
using next = indices< Ns..., sizeof...(Ns) >;
};


template< std::size_t N >
struct make_indices
{
using type = typename make_indices< N - 1 >::type::next;
};


template<>
struct make_indices< 0 >
{
using type = indices<>;
};


// we need something to find a type's index within a list of types
template<typename T, typename U, std::size_t = 0>
struct index {};


template<typename T, typename... Us, std::size_t N>
struct index<T, std::tuple<T, Us...>, N>
: std::integral_constant<std::size_t, N>{};


template<typename T, typename U, typename... Us, std::size_t N>
struct index<T, std::tuple<U, Us...>, N>
: index<T, std::tuple<Us...>, N + 1>{};


// we need a way to remove duplicate types from a list of types
template<typename T, typename I = void> struct unique;


// step 1: generate indices
template<typename... Ts>
struct unique< std::tuple<Ts...>, void >
: unique< std::tuple<Ts...>, typename make_indices<sizeof...(Ts)>::type >
{
};


// step 2: remove duplicates. Note: No recursion here!
template<typename... Ts, std::size_t... Is>
struct unique< std::tuple<Ts...>, indices<Is...> >
{
using type = decltype(std::tuple_cat(std::declval<
typename std::conditional<index<Ts, std::tuple<Ts...>>::value == Is, std::tuple<Ts>, std::tuple<>>::type
>()...));
};


// a helper to turn Ts... into std::vector<Ts>...
template<typename> struct vectorize;


template<typename... Ts>
struct vectorize<std::tuple<Ts...>>
{
using type = std::tuple< std::vector<Ts>... >;
};


// now you can easily use it to define your Store
template<typename... Ts> class Store
{
public:
template<typename T> void add(T mValue) {
slot<T>().push_back(mValue);
}


template<typename T> std::vector<T>& get() {
return slot<T>();
}
private:
using Storage = typename vectorize<typename unique<std::tuple<Ts...>>::type>::type;
Storage storage;


template<typename T>
decltype(std::get<index<T, typename unique<std::tuple<Ts...>>::type>::value>(storage))
slot()
{
return std::get<index<T, typename unique<std::tuple<Ts...>>::type>::value>(storage);
}
};


class Store_Helper
{
public:
template< class... Args>
Store<Args...> operator()(const Args&... args)
{
auto helper = [](auto... param) {
Store<decltype(param)...> stream;
using List = int[];
(void)List{ 0, ((void)(stream.add(param)), 0) ... };
return stream;
};
return helper(args...);
}
};


int main()
{
Store_Helper store_helper;
auto store = store_helper(1, 2, std::string("test1"), std::string("test2"), 3.5, 2.5);

std::cout<< store.get<int>()[0] <<'\n';//integer aval
std::cout<< store.get<int>()[1] <<'\n';//integer dovom
std::cout<< store.get<std::string>()[1] <<'\n';//string dovom
std::cout<< store.get<double>()[1];//double dovom
}

ضمنا vs2013 خیلی چیزا رو پشتیبانی نمی کنه کد بالا فقط توی آخرین نسخه های gcc یا clang اجرا میشه .
http://coliru.stacked-crooked.com/a/45b3f17905361921 (http://coliru.stacked-crooked.com/a/66d4109121be17a7)