Pertanyaan Panggilan ambigu tidak dihindari oleh SFINAE


Kompilasi kode ini:

#include <iostream>


template <int N>
struct TestClass {
    template <int N2, typename std::enable_if<N2 == N, int>::type = 0>
    void doAction() { std::cout << "TestClass::doAction<" << N << ">();\n"; }
};

struct HostClass : public TestClass<1>, public TestClass<2> {
};


int main(int argc, const char * argv[]) {
    HostClass hostClass;

    hostClass.doAction<1>();
    hostClass.doAction<2>();

    return 0;
}

menyebabkan kesalahan panggilan ambigu karena doAction keduanya dalam TestClass<1> dan TestClass<2> kelas induk.

main.cpp: 33: 15: Member 'doAction' yang ditemukan dalam beberapa kelas dasar dari berbagai tipe

Tapi std::enable_if tidak akan menonaktifkan ambiguitas ini?

EDIT:

Saya pikir alasan sebenarnya untuk ambiguitas ini adalah sama dari pada pertanyaan ini:

Mengapa beberapa fungsi yang diwariskan dengan nama yang sama tetapi tanda tangan yang berbeda tidak diperlakukan sebagai fungsi yang kelebihan beban?

Ambiguitas dapat diselesaikan seperti yang ditunjukkan dalam jawaban dengan using kata kunci:

#include <iostream>


template <int N>
struct TestClass {
    template <int N2, typename std::enable_if<N2 == N, int>::type = 0>
    void doAction() { std::cout << "TestClass::doAction<" << N << ">();\n"; }
};

struct HostClass : public TestClass<1>, public TestClass<2> {
    using TestClass<1>::doAction;
    using TestClass<2>::doAction;
};

int main(int argc, const char * argv[]) {
    HostClass hostClass;

    hostClass.doAction<1>();    // OK, compile
    hostClass.doAction<2>();    // OK, compile
    //hostClass.doAction<3>();  // OK, doesn't compile : "candidate template ignored: disabled by 'enable_if' [with N2 = 3]"

    return 0;
}

Saya tidak tahu apakah itu yang dimaksud dengan jawaban @skypjack tetapi saya tetap membiarkannya karena metode alternatifnya.


5
2017-11-12 20:59


asal


Jawaban:


Itu akan (biarkan aku katakan) penurunan salah satu dari dua fungsi setelah substitusi.
Bagaimanapun, pertama-tama compiler harus memutuskan fungsi mana yang ingin Anda gunakan ketika Anda memanggilnya sebagai doAction<1>, kemudian itu dapat melanjutkan dengan substitusi dan akhirnya membuang fungsi yang dipilih karena sfinae.
Pada titik doa, keduanya adalah kandidat yang sah dan panggilan itu sebenarnya ambigu.

Perhatikan bahwa, seperti yang disarankan oleh @ Peregring-lk di komentar, TestClass<1>::doAction dan TestClass<2>::doAction adalah dua fungsi yang berbeda ditempatkan di ruang nama yang berbeda, mereka tidak overloads dari fungsi yang sama.
Ini sebenarnya adalah sumber kesalahpahaman yang umum.


Anda dapat dengan mudah memecahkan masalah seperti berikut:

#include <iostream>

template <int N>
struct TestClass {
    void doAction() { std::cout << "TestClass::doAction<" << N << ">();\n"; }
};

struct HostClass : public TestClass<1>, public TestClass<2> {
    template<int N>
    void doAction() { return TestClass<N>::doAction(); }
};


int main(int argc, const char * argv[]) {
    HostClass hostClass;

    hostClass.doAction<1>();
    hostClass.doAction<2>();

    return 0;
}

5
2017-11-12 21:05