Это хорошо компилируется в Clang 3.3:
template <typename T>
struct M;
template <typename R, typename C, typename... A>
struct M <R (C::*)(A...)> { };
template <typename R, typename C, typename... A>
struct M <R (C::*)(A...) &> { };
но терпит неудачу в gcc 4.8.1:
[...] error: redefinition of ‘struct M <R (C::*)(A ...)>’
struct M <R (C::*)(A...) &> { };
^
[...] error: previous definition of ‘struct M <R (C::*)(A ...)>’
struct M <R (C::*)(A...)> { };
^
При использовании в разных контекстах это приводит к неожиданным действиям компилятора, таким как сбой или внутренние ошибки компилятора.
Я понимаю, что ref-квалифицированные функции-члены называются «ссылками rvalue для * this» (N2439) в стандарте, и являются поддерживается gcc 4.8.1.
Проблема здесь состоит в том, чтобы использовать их в качестве аргументов шаблона, где gcc, по-видимому, не делает различий между квалифицированным и обычным типом функции-члена.
Реализация библиотеки std в clang обнаруживает, поддерживается ли эта функция
__has_feature(cxx_reference_qualified_functions)
Итак, является ли это использование стандартных функций ref или расширением языка?
Согласно пункту 6 пункта 8.3.5 [dcl.fct] (я добавил некоторые выделения в цитируемый текст):
Тип возвращаемого значения, тип-списка параметров, реф-классификатор, и cv-qualifier-seq, но не аргументы по умолчанию (8.3.6) или спецификация исключения (15.4), являются частью типа функции.
То есть, ref-квалификатор, безусловно, является частью типа. Далее в соответствии с 8.4.1 [dcl.fct.def.general] параграф 5 вы можете создавать указатели на члены, включая ref-qualifiers:
Cv-qualifier-seq или реф-классификатор (или оба) может быть частью объявление нестатической функции-члена, определение нестатической функции-члена или только указатель на функцию-член (8.3.5); см. 9.3.2.
Нет конкретного ограничения, что указатель на функции-члены с ref-qualifier не может быть использован в качестве нетиповых аргументов шаблона. То есть, я думаю, что частичная специализация, которую вы пытались использовать, должна работать. Однако поддержка ref-квалификаторов является довольно новой функцией как в clang, так и в gcc, то есть, вероятно, не все угловые случаи были сглажены. Я попробовал приведенное выше с довольно свежими снимками gcc (20130811) и clang (trunk 190769), и оба скомпилировали код в порядке. Конечно, этот фрагмент на самом деле ничего не делает, и я не пытался злоупотреблять этой функцией. Я полагаю, что вы только что вызвали несколько ошибок компилятора, и я уверен, что оба проекта оценят сообщения об ошибках на их последних снимках.
Других решений пока нет …