Вот соответствующие цитаты, но окончательный ответ во многом зависит от интерпретации.
N3797 6.4.2 / 2:
Условие должно быть цельного типа, типа перечисления или типа класса , Если тип класса, условие контекстно неявно преобразуется (раздел 4) в интегральный или перечисляемый тип.
blockquote>4/5:
Определенные языковые конструкции требуют преобразования в значение, имеющее один из определенного набора типов, соответствующих конструкции. Выражение
blockquote>e
типа классаE
, появляющееся в таком контексте, называется , контекстно неявно преобразованным в заданным типомT
и хорошо сформированным тогда и только тогда, когдаe
может неявно преобразуется в типT
, который определяется следующим образом:E
выполняется поиск функций преобразования, возвращаемым типом которых является cvT
или ссылка на cvT
, чтоT
разрешено контекстом. Должен быть ровно один такойT
.14.5.2 / 6:
Специализация функции преобразования не найдена при поиске по имени. Вместо этого рассматриваются все шаблоны функций преобразования, видимые в контексте использования. Для каждого такого оператора, если вывод аргумента преуспевает (14.8.2.3), полученная специализация используется, как если бы она была найдена путем поиска по имени.
blockquote>14.5.2 / 8:
Разрешение перегрузки (13.3.3.2) и частичное упорядочение (14.5.6.2) используются для выбора наилучшей функции преобразования между несколькими специализациями шаблонов функций преобразования и / или функциями преобразования без шаблона.
blockquote >Интерпретация 1: 4/5 гласит «функции преобразования», а не «функции преобразования и шаблоны функций преобразования». Поэтому
Var::operator int() const
является единственным вариантом, а clang является правильным.Интерпретация 2 [слабый?]: 14.5.2 требует от нас сравнить шаблон функции преобразования путем разрешения перегрузки и частичного упорядочения на том же начальном как функция преобразования без шаблона. Они сравнивают специализированные функции и функции шаблонов, а не шаблоны функций, поэтому мы будем делать вывод аргумента шаблона. Вычисление аргумента шаблона для шаблона функции преобразования требует целевого типа. Хотя у нас обычно есть более четкий тип цели, в этом случае мы просто попробуем (теоретически все) все типы в наборе допустимых типов. Но ясно, что функция без шаблона является лучшей жизнеспособной функцией, которая включает все специализированные шаблоны, поэтому разрешение перегрузки выбирает функцию без шаблона. clang является правильным.
Интерпретация 3: Поскольку для разрешения перегрузки требуется вычет аргумента шаблона, а вывод аргумента шаблона требует известного целевого типа, сначала следует рассмотреть семантику 4/5, а затем ее преобразованный тип (если любой) может использоваться для процесса разрешения перегрузки. 14.5.2 требует рассмотрения шаблона функции преобразования, но затем мы обнаруживаем, что существует несколько допустимых типов
T
, для которых у нас есть функция преобразованияT
[эта функция, возможно, является специализированной функцией). Программа плохо сформирована, поэтому g ++ корректна.
Нестатическую функцию-член нужно вызывать с объектом. То есть он всегда неявно передает «этот» указатель в качестве своего аргумента.
Поскольку ваша подпись std::function
указывает, что ваша функция не принимает никаких аргументов (<void(void)>
), вы должны bind первый (и единственный) аргумент.
std::function<void(void)> f = std::bind(&Foo::doSomething, this);
Если вы хотите связать функцию с параметрами, вам нужно указать заполнители:
using namespace std::placeholders;
std::function<void(int,int)> f = std::bind(&Foo::doSomethingArgs, this, _1, _2);
Или , если ваш компилятор поддерживает C ++ 11 lambdas:
std::function<void(int,int)> f = [=](int a, int b) {
this->doSomethingArgs(a, b);
}
(у меня нет компилятора C ++ 11 под рукой прямо сейчас , поэтому я могу " t проверить это.)
Вам нужно
std::function<void(Foo*)> f = &Foo::doSomething;
, чтобы вы могли вызвать его на любом экземпляре, или вам нужно связать конкретный экземпляр, например this
std::function<void(void)> f = std::bind(&Foo::doSomething, this);
Если вам нужно сохранить функцию-член без экземпляра класса, вы можете сделать что-то вроде этого:
class MyClass
{
public:
void MemberFunc(int value)
{
//do something
}
};
// Store member function binding
auto callable = std::mem_fn(&MyClass::MemberFunc);
// Call with late supplied 'this'
MyClass myInst;
callable(&myInst, 123);
. Каким будет тип хранилища без auto ? Что-то вроде этого:
std::_Mem_fn_wrap<void,void (__cdecl TestA::*)(int),TestA,int> callable
Вы также можете передать это хранилище функций стандартным связям функций
std::function<void(int)> binding = std::bind(callable, &testA, std::placeholders::_1);
binding(123); // Call
Предыдущие и будущие примечания: более старый интерфейс std :: mem_func , но с тех пор он устарел. Существует предложение, post C ++ 17, чтобы сделать указателем на функции-члены, вызываемые . Это было бы очень приятно.
std::mem_fn
удален не ; куча ненужных перегрузок. С другой стороны, std::mem_fun
устарел с C ++ 11 и будет удален с C ++ 17.
– Max Truxa
3 November 2016 в 16:47