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

Как шаблонные переменные NAMES, а не типы?

мой вопрос в том, как шаблонное имя члена класса, которое должно использоваться.

Может быть, упрощенный и псевдо-пример:

/** 
Does something with a specified member of every element in a List.
*/
template<membername MEMBER> // <-- How to define such thing?
void doSomething(std::vector<MyClass> all){

    for( i=0; i < all.size(); i++)
      all[i].MEMBER++; // e.g.; use all[i].MEMBER in same way

}

и

class MyClass{
public:
    int aaa, bbb, ccc;
}

и приложение:

main(){
    vector<MyClass> all = ....

    // applicate doSomething() to all aaa's
    doSomething<aaa>(all);  // or:
    doSomething<MyClass::aaa>(all); // or:
    doSomething<?????>(all);
}

Как должно выглядеть определение шаблона, что я могу переключить, какая переменная-член (aaa, bbb или ccc) MyClass доступна или изменена в doSomething (.)?
В моей реальной мировой задаче все ЧЛЕНЫ имеют тот же тип, что и выше.

Спасибо, Tebas

4b9b3361

Ответ 1

Параметры шаблона ограничены типами, целыми константами, указателями/ссылками на функции или объекты с внешней привязкой и указателями-членами, но без идентификаторов.

Но вы можете использовать указатель-член в качестве параметра шаблона:

template<int MyClass::* MemPtr>
void doSomething(std::vector<MyClass> & all) {
   for( i=0; i < all.size(); i++)
      (all[i].*MemPtr)++;
}

:

doSomething<&MyClass::aaa>(all);

Обратите внимание, что я изменил функцию doSomething, чтобы взять ссылку вместо того, чтобы принимать вектор по значению.

Ответ 2

sellibitze решение в порядке (хотя, честно говоря, не очень: см. мое редактирование), только это ограничивает использование только членов типа int. Более общим решением было бы это (хотя элемент здесь не является параметром шаблона)

#include <vector>

struct MyClass
{
   int i;
   char c;
};

template <class T>
void DoSomething(std::vector<MyClass>& all, T MyClass::* MemPtr)
{ 
   for(std::vector<MyClass>::size_type i = 0; i < all.size(); ++i)
      (all[i].*MemPtr)++;
}

int main()
{
   std::vector<MyClass> all;
   DoSomething(all, &MyClass::i);
   DoSomething(all, &MyClass::c);
}

EDIT: Также обратите внимание, что обычно не рекомендуется указывать, что элемент является параметром шаблона, поскольку могут передаваться только такие указатели, которые известны временем компиляции, то есть вы не можете определить время выполнения указателя, а затем передать его как параметр шаблона.

Ответ 3

Я бы использовал лямбда для решения этой проблемы. Что-то вроде этого:

#include <vector>     // vector
#include <algorithm>  // for_each
#include <functional> // function

struct MyClass {
   void func1() const { std::cout << __FUNCTION__ << std::endl; }
   void func2() const { std::cout << __FUNCTION__ << std::endl; }
};

void doSomething(std::vector<MyClass> all, std::function<void (MyClass& m)> f)
{
   std::for_each(all.begin(), all.end(), f);
}

int main()
{
   std::vector<MyClass> all;
   all.push_back(MyClass());

    // apply various methods to each MyClass:
   doSomething(all, [](MyClass& m) { m.func1(); });
   doSomething(all, [](MyClass& m) { m.func2(); });
}

Конечно, в этом случае функция doSomething не нужна. Я мог просто просто называть for_each непосредственно на all.