Yet another MSVC 2015 decltype bug?
От: SaZ  
Дата: 04.04.16 13:46
Оценка: 1 (1)
Есть такой код:

class Test
{
public:
    void foo()
    {
        std::cout << 0 << std::endl;
    }
 
    template< int N >
    void fooN()
    {
        std::cout << N << std::endl;
    }
 
    template< typename Fn >
    void invoke( Fn&& fn )
    {
        (*this.*fn)();
    }
 
};
 
int main( int args, char *argv[] )
{
    Test test;
 
    using Fn = decltype(&Test::fooN<1>);
    test.invoke<Fn>( &Test::foo );  // В моей задаче автовыведение типа не прокатит
    test.invoke<Fn>( &Test::fooN<1> );
 
    return 0;
}


Это студия тупит или я чего-то не понимаю? В студии не компилируется — говорит, что cannot convert argument 1 from 'void (__thiscall Test::* )(void)' to 'Fn (__thiscall &&)'.
Я так понимаю, что студия считает, что Test::fooN<1> это перегрузка. Но, перегрузка — это когда имя метода совпадает, а сигнатуры отличаются. Тут же сигнатуры совпадают, а имена методов — хз
Отредактировано 04.04.2016 13:55 SaZ . Предыдущая версия .
Re: Yet another MSVC 2015 decltype bug?
От: B0FEE664  
Дата: 04.04.16 14:35
Оценка: 6 (1)
Здравствуйте, SaZ, Вы писали:

SaZ>Это студия тупит или я чего-то не понимаю? В студии не компилируется — говорит, что cannot convert argument 1 from 'void (__thiscall Test::* )(void)' to 'Fn (__thiscall &&)'.

SaZ>Я так понимаю, что студия считает, что Test::fooN<1> это перегрузка. Но, перегрузка — это когда имя метода совпадает, а сигнатуры отличаются. Тут же сигнатуры совпадают, а имена методов — хз

Я не знаю как оно должно быть, но вот так компилируется и запускается:
    auto aF1 =  &Test::fooN<1>;
    using Fn1 = decltype(aF1);
    test.invoke<Fn1>( &Test::fooN<1> );
    test.invoke<Fn1>( &Test::foo );



PS Короче, это bug MS
https://connect.microsoft.com/VisualStudio/feedback/details/775434/decltype-is-buggy-in-vs-2012
https://connect.microsoft.com/VisualStudio/feedback/details/1029542

Исправлять отказываются, предлагают обход:
    template <typename T> T identity(T);
...
    using a = decltype(identity(&Test::fooN<1>));
    test.invoke<a>( &Test::foo );
    test.invoke<a>( &Test::fooN<1> );
И каждый день — без права на ошибку...
Отредактировано 04.04.2016 15:09 B0FEE664 . Предыдущая версия . Еще …
Отредактировано 04.04.2016 15:00 B0FEE664 . Предыдущая версия .
Re: Yet another MSVC 2015 decltype bug?
От: tstalker Украина  
Дата: 04.04.16 14:46
Оценка: -1
Здравствуйте, SaZ, Вы писали:

SaZ>Это студия тупит или я чего-то не понимаю? В студии не компилируется — говорит, что cannot convert argument 1 from 'void (__thiscall Test::* )(void)' to 'Fn (__thiscall &&)'.

SaZ>Я так понимаю, что студия считает, что Test::fooN<1> это перегрузка. Но, перегрузка — это когда имя метода совпадает, а сигнатуры отличаются. Тут же сигнатуры совпадают, а имена методов — хз

Не будет ли любезен уважаемый джинн пояснить, на кой ему здесь класс?
Стоит убрать из твоего кода класс — и всё заработает:
#include <iostream>

void foo()
{
    std::cout << 0 << std::endl;
}

template<int N>
void fooN()
{
    std::cout << N << std::endl;
}

template<typename Fn>
void invoke(Fn&& fn)
{
    fn();
}

int main()
{
    using Fn = decltype(&fooN<1>);
    invoke<Fn>(&foo);
    invoke<Fn>(&fooN<1>);
}

Но ежели этот класс тебе дорог как память — юзай обёртку std::mem_fn()
Re[2]: Yet another MSVC 2015 decltype bug?
От: SaZ  
Дата: 04.04.16 15:18
Оценка:
Здравствуйте, tstalker, Вы писали:

T>Не будет ли любезен уважаемый джинн пояснить, на кой ему здесь класс?

T>Стоит убрать из твоего кода класс — и всё заработает:

Это как-бы тестовый пример. В реальной задаче всё несколько сложнее: C++ враппер вокруг одной си-шной библиотеки, со своим, достаточно специфическим, механизмом коллбэков. Немного повелосипедил с асинхронными межпоточными вызовами на чистом С++, сделав синтаксис, похожий на Qt-шный QObject::connect.
Отредактировано 04.04.2016 15:22 SaZ . Предыдущая версия .
Re[3]: Yet another MSVC 2015 decltype bug?
От: tstalker Украина  
Дата: 04.04.16 15:51
Оценка:
Здравствуйте, SaZ, Вы писали:

SaZ>Это как-бы тестовый пример. В реальной задаче всё несколько сложнее: C++ враппер вокруг одной си-шной библиотеки, со своим, достаточно специфическим, механизмом коллбэков. Немного повелосипедил с асинхронными межпоточными вызовами на чистом С++, сделав синтаксис, похожий на Qt-шный QObject::connect.


Ok, бро. Хочешь с классом — лови:
#include <iostream>
#include <functional>

class Test
{
public:
    void foo()
    {
        std::cout << 0 << std::endl;
    }

    template<int N>
    void fooN()
    {
        std::cout << N << std::endl;
    }

    template<typename Fn>
    void invoke(Fn&& fn)
    {
        fn(this);
    }
};

int main()
{
    using Fn = decltype(std::mem_fn(&Test::fooN<1>));
    Test test;
    test.invoke<Fn>(std::mem_fn(&Test::foo));
    test.invoke<Fn>(std::mem_fn(&Test::fooN<1>));
}
Re: Yet another MSVC 2015 decltype bug?
От: szag  
Дата: 05.04.16 05:32
Оценка:
Здравствуйте, SaZ, Вы писали:

SaZ>Это студия тупит или я чего-то не понимаю? В студии не компилируется — говорит, что cannot convert argument 1 from 'void (__thiscall Test::* )(void)' to 'Fn (__thiscall &&)'.

SaZ>Я так понимаю, что студия считает, что Test::fooN<1> это перегрузка. Но, перегрузка — это когда имя метода совпадает, а сигнатуры отличаются. Тут же сигнатуры совпадают, а имена методов — хз

похоже во 2-м апдейте поправили
Re: Fixed in update 2
От: SaZ  
Дата: 06.04.16 10:16
Оценка:
MSVC 2015 update 2 — полёт нормальный. Так что починили.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.