2015-04-18 3 views
4

Я получил этот класс:Функции указатель шаблона класса член

template <class T> 
class list 
{ 
    ... 
    bool moreThan(T x, T y); 
    bool lessThan(T x, T y); 
    ... 
}; 

мне нужен указатель на функцию, чтобы изменить поведение моего класса, и переключаться между использованием bool moreThan(T, T) или bool lessThan(T, T). Так что я в настоящее время использую:

bool (list<int>::*foo)(int x, int y); 
foo = &list<int>::lessThan; 

и использовать его:

(this->*foo)(x, y); 

, но я хотел бы иметь гибкий указатель на функцию, так что я могу использовать его с какой T мне нужно, не только int. Итак, есть ли способ создать указатель на элемент шаблона класса? Что-то вроде:

template <class T> 
bool (list<T>::*foo)(T x, T y); //this doesn't work 
+3

Вы будете бороться с этим, потому что каждая специализация 'list' может иметь другое определение этих функций или даже не определять их вообще! –

ответ

2

Нет, нет. Указатель-к-член должен указывать на что-то. Функция-член в шаблоне класса не является одной функцией, это семейство функций, и каждый из них имеет другой тип. Там может быть даже T, для которого list<T>::lessThan не существует или является типом или переменной!

Если мы сделали псевдоним для одного такого указателя на член:

template <typename T> 
using CompFun = bool (list<T>::*)(T, T); 

Тогда очевидно, что CompFun<int> и CompFun<string> различные типы. Вы не можете создать общую переменную CompFun<T>.

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

+0

Я очень хочу, чтобы вы прекратили использовать этот двусмысленный термин «метод». –

+2

@ LightningRacisinObrit Что в этом двусмысленно? – Barry

+2

Термин «метод» не определен в C++. Вы имели в виду функцию, которая является членом? Или тот, который не статичен? Или тот, который является виртуальным? Или тот, который чист? Чтобы избежать недоразумений, предпочитайте стандартизованную терминологию: вместо 'method 'say' function 'с префиксом тех спецификаторов, которые имеют значение.Мы здесь не делаем Java. –

2

В настоящее время вы должны сделать что-то вроде этого:

template <typename T> 
struct listComparePtr 
{ 
    typedef bool (list<T>::*type)(T x, T y); 
}; 

Использование так:

listComparePtr<int>::type foo = &list<int>::lessThan; 
listComparePtr<double>::type foo2 = &list<double>::moreThan; 
0

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

Однако ваша попытка объявления уже является допустимым шаблоном переменной C++ 14. Пример: http://coliru.stacked-crooked.com/a/b1f0904e0ee4d6ad

Аналогично, можно поместить в шаблонов С ++ 14 лямбда общего: с

auto foo = [](auto && l, auto && x, auto && y) 
      { return l.moreThan(x, y); }; 

Это имеет то преимущество, что дает вам ручку, которая является один тип, хотя функция внутри лямбда по-прежнему является шаблоном.