У меня есть код, который компилируется с использованием msvc, но не под gcc. Я хотел бы знать, является ли это нестандартной функцией msvc или ошибкой в gcc (или, вернее, версия v5.0.3 MinGW)

Рассмотрим следующий код:

template <class T>
struct object_with_func_ptr {
    const T func; // An object to hold a const function pointer.
};

class foo {
public:
    void bar() {} // The function I want to point to.

    static constexpr auto get_bar() {
        return object_with_func_ptr<decltype(&bar)>{&bar}; // A constexpr to wrap a function pointer.
    }
};

template <class Func, Func Fn> struct template_using_func {};

int main() {
    constexpr auto bar_obj = foo::get_bar();
    // Note that this is a constexpr variable and compiles for gcc also if the template_using_func line is left out.
    constexpr auto bar_func_ptr = bar_obj.func;
    template_using_func<decltype(bar_func_ptr), bar_func_ptr>();
    return 0;
}

В случае, если это нестандартная функция msvc, было бы здорово узнать, есть ли другие способы достичь того, что я собираюсь сделать.

РЕДАКТИРОВАТЬ: Здесь ошибка компилятора, созданная MinGW:

E:\CLion\ErrorExample\main.cpp: In function 'int main()':
E:\CLion\ErrorExample\main.cpp:21:61: error: 'bar_func_ptr' is not a valid template argument for type 'void (foo::* const)()'
template_using_func<decltype(bar_func_ptr), bar_func_ptr>();
                                                        ^
E:\CLion\ErrorExample\main.cpp:21:61: error: it must be a pointer-to-member of the form '&X::Y'
E:\CLion\ErrorExample\main.cpp:21:61: error: could not convert template argument 'bar_func_ptr' from 'void (foo::* const)()' to 'void (foo::* const)()'

ИЗМЕНИТЬ 2: Изменение &bar на &foo::bar, очевидно, делает эту компиляцию и для clang (как отмечено в комментариях), так что в настоящее время я предполагаю, что это ошибка GCC.

3
Chartas 8 Янв 2018 в 22:41

2 ответа

Лучший ответ

До C ++ 17 стандарт ограничивал ненулевые аргументы шаблона указателя на член до "указатель на член, выраженный, как описано в [expr.unary. op] ". Другими словами, такой аргумент должен быть выражен в точной форме &A::B.

C ++ 17 ослабляет это ограничение, чтобы разрешить общие константные выражения. Похоже, что это еще не реализовано в GCC.

4
T.C. 8 Янв 2018 в 20:52

Ну, есть несколько очевидных ошибок, например &bar вместо &foo::bar. Если мы их исправим, Clang соглашается с MSVC, и когда 2 из 3 основных компиляторов соглашаются, и это заставляет В смысле, я придерживаюсь разумного большинства.

Когда я тестирую это на gcc, возникает ошибка void (foo::* const)()' to 'void (foo::* const)(), что заставляет меня думать, что это ошибка. Теперь это может быть какое-то неясное требование для аргументов шаблона, не являющегося типом, из определенных категорий значений, которое здесь не выполняется, но тогда я бы ожидал более четкого сообщения об ошибке.

Кроме того, std::integral_constant может лучше представлять указатель функции времени компиляции. чем ваш класс, если вы действительно не хотите, чтобы во время выполнения изменялась точка указателя.

0
Yakk - Adam Nevraumont 8 Янв 2018 в 20:36