Как шаблонизировать переменные NAMES, а не типы? - PullRequest
12 голосов
/ 15 октября 2010

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

Возможно, упрощенный и псевдо-пример:

/** 
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 (.)?
В моей реальной задаче все ЧЛЕНЫ относятся к тому же типу, что и выше.

Спасибо, Тебас

Ответы [ 3 ]

18 голосов
/ 15 октября 2010

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

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

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 , чтобы получать ссылку вместо принятия вектора по значению.

10 голосов
/ 15 октября 2010

Решение 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: Также обратите внимание, что указатель на член обычно не является хорошим параметром шаблона, поскольку могут передаваться только такие указатели, которые известны во время компиляции , то есть вы не можете определить время выполнения указателя, а затем передать его как параметр шаблона.

1 голос
/ 15 октября 2010

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

#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.

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