Panggil fungsi anggota templat dengan std::async

Apakah mungkin dan bagaimana cara memanggil fungsi anggota templat suatu kelas menggunakan std::async (sebaiknya tanpa menggunakan std::bind)? Tolong jelaskan jika standar C++11 atau C++14 mengizinkan panggilan seperti itu secara umum dan bagaimana membuatnya berfungsi di MSVS2013 pada khususnya.

#include <future>

template<typename T> void non_member_template(T val) {}

struct X
{
    void member_non_template(int val) {}
    template<typename T> void member_template(T val) {}
    void call()
    {
        int val = 123;
        std::async(std::launch::async, &non_member_template<int>, val); // ok
        std::async(std::launch::async, &X::member_non_template, this, val); // ok
        std::async(std::launch::async, &X::member_template<int>, this, val); // error
    }
};

int main()
{
    X x;
    x.call();
}

person PowerGamer    schedule 16.01.2015    source sumber
comment
Ini harus dikompilasi, saya tidak mendapatkan kesalahan dengan gcc atau dentang. Mungkin ada bug di MSVC.   -  person 0x499602D2    schedule 16.01.2015
comment
@ 0x499602D2 Kompiler yang berbeda memberikan pesan kesalahan yang berbeda dan karena templat yang terlibat, kompiler tersebut panjang dan tidak dapat dipahami. Saya mendapatkan kesalahan dari MSVS2013 dan MSVS2015 (di rise4fun.com) dan beberapa versi GCC saat memilih C++14 di ideone.com.   -  person PowerGamer    schedule 16.01.2015
comment
Saat membangun VS2013, saya mendapatkan kesalahan ini: MSB6006: "CL.exe" exited with code 1. dan tidak ada informasi lainnya.   -  person derpface    schedule 16.01.2015
comment
Kompiler yang berjalan di Ideone tidak mendukung multithreading. Kesalahannya adalah referensi yang tidak ditentukan - tidak ada hubungannya dengan templat. Anda dapat melihatnya dikompilasi di sini. Ini mungkin hanya bug di perpustakaan thread yang dikirimkan bersama MSVC.   -  person 0x499602D2    schedule 16.01.2015
comment
@0x499602D2 Dilaporkan sebagai bug di connect.microsoft.com/VisualStudio/feedback/details/1090183 . Mari kita lihat apa yang dikatakan Microsoft mengenai hal ini.   -  person PowerGamer    schedule 16.01.2015
comment
sementara itu kamu dapat melemparkannya: std::async(std::launch::async, (void(X::*)(int))&X::member_template<int>, this, val);   -  person Axalo    schedule 17.01.2015
comment
Casting seperti menerapkan kekerasan. Dalam hal ini, itu memberikan kekuatan yang lebih brutal karena Anda menyarankan pemeran gaya C. Menggunakan kekerasan ketika Anda tidak memahami sesuatu adalah... ya, Anda mengerti.   -  person Ulrich Eckhardt    schedule 17.01.2015


Jawaban (2)


Saya belum pernah melihat kode memecahkan kompiler sebelumnya, tapi ini dia:

kesalahan MSB6006: CL.exe keluar dengan kode 1

Saya menyarankan hal yang sama seperti Axalo di komentar di atas, Anda dapat mengatasi kesalahan kompilasi dengan melakukan casting.

#include <future>

template<typename T> void non_member_template( T val ) {}

struct X
{
    void member_non_template( int val ) {}
    template<typename T> void member_template( T val ) {}
    void call()
    {
        int val = 123;
        std::async( std::launch::async,  &non_member_template<int>, val ); // ok
        std::async( std::launch::async, &X::member_non_template, this, val ); // ok
        //std::async( std::launch::async, &X::member_template<int>, this, val ); // error
        std::async( std::launch::async, static_cast< void ( X::* )( int )>( &X::member_template<int> ), this, val ); // ok
    }
};

int main()
{
    X x;
    x.call();
}
person sbsmith    schedule 17.01.2015

Rupanya itu adalah bug di Microsoft Visual C++ 2013 dan Pratinjau 2015 yang akan diperbaiki di versi Visual C++ mendatang: Meneruskan fungsi templat anggota ke std::async menghasilkan kesalahan kompilasi.

Jadi program contohnya adalah kode C++ yang valid dan jika Anda memerlukan solusi untuk Visual C++ 2013 gunakan cast pada panggilan terakhir ke std::async seperti yang disarankan dalam komentar:

static_cast<void(X::*)(int)>(&X::member_template<int>)
person PowerGamer    schedule 31.01.2015