簡體   English   中英

select 無法使用 MSVC 正確的運算符==,但不能使用模板化的 gcc/clang class

[英]Failure to select correct operator== with MSVC but not gcc/clang for templated class

以下示例使用 gcc 和 clang 編譯良好,但無法在 MSVC 中編譯。 我想知道我是否無意中跌入了非標准領域? 如果不是,哪個編譯器是正確的? 是否有解決方法? 最小示例 ( https://godbolt.org/z/PG35hPGMW ):

#include <iostream>
#include <type_traits>

template <class T>
struct Base { 
    Base() = default;
    Base(T) {}
    static constexpr bool isBase = true;
};


template <class U>
constexpr std::enable_if_t<U::isBase, bool> EnableComparisonWithValue(U const *) {
  return false;
}

template <class>
constexpr bool EnableComparisonWithValue(...) {
  return true;
}


template <class T, class U>
bool operator==(Base<T> const &, Base<U> const &) {
    std::cout << "operator==(Base, Base)" << std::endl;
    return true;
}

template <class T, class U,
          std::enable_if_t<EnableComparisonWithValue<U>(nullptr), int> = 0>
bool operator==(Base<T> const &, U const &) {
    std::cout << "operator==(Base, U)" << std::endl;
    return true;
}

template <class U, class T,
          std::enable_if_t<EnableComparisonWithValue<U>(nullptr), int> = 0>
bool operator==(U const &, Base<T> const &) {
    std::cout << "operator==(U, Base)" << std::endl;
    return true;
}


int main() {
    Base<int> b1, b2;
    b1 == 42; // gcc and clang compile, msvc does not
}

MSVC 拋出編譯錯誤C2676: binary '==': 'Base<int>' does not define this operator or a conversion to a type acceptable to the predefined operator clang 和 gcc 按預期調用operator==(Base, U) 有趣的是,如果我刪除Base中的所有成員並將其定義為template <class T> struct Base{}; .

背景:我有另一個 class template <class T> Derived: Base<T>不包含附加數據。 我想重用所有operator==而不必為Derived重新定義它們。 如果沒有 SFINEA 的東西,將Derived<int>int進行比較會導致模糊的運算符調用,因為底部的兩個operator==定義將U推斷為Derived<int> (AFAIK 正確)。 所以我的想法是禁用它們以強制編譯器使用operator==(Base<T> const &, Base<U> const &) 但后來我遇到了上述問題。

此外,除了為BaseDerived的所有組合定義運算符之外,是否還有解決方法?

我很驚訝 MSVC 沒有編譯你的代碼,這在我看來是完全正確的。

所以...不確定...但我想這是一個 MSVC 錯誤。

無論如何...考慮到您還要求解決方法...我看到如果您啟用/禁用運算符的返回類型,MSVC 也適用於 SFINAE,所以我建議您按如下方式重寫運算符

template <class T, class U>
std::enable_if_t<EnableComparisonWithValue<U>(nullptr), bool> operator==(Base<T> const &, U const &) {
    std::cout << "operator==(Base, U)" << std::endl;
    return true;
}

template <class U, class T>
std::enable_if_t<EnableComparisonWithValue<U>(nullptr), bool> operator==(U const &, Base<T> const &) {
    std::cout << "operator==(U, Base)" << std::endl;
    return true;
}

以下是一個完整的編譯示例,其中還有一個Derived class

#include <iostream>
#include <type_traits>

template <class T>
struct Base { 
    Base() = default;
    Base(T) {}
    static constexpr bool isBase = true;
};

struct Derived : public Base<int>
{ };

template <class U>
constexpr std::enable_if_t<U::isBase, bool> EnableComparisonWithValue(U const *) {
  return false;
}

template <class>
constexpr bool EnableComparisonWithValue(...) {
  return true;
}


template <class T, class U>
bool operator==(Base<T> const &, Base<U> const &) {
    std::cout << "operator==(Base, Base)" << std::endl;
    return true;
}

template <class T, class U>
std::enable_if_t<EnableComparisonWithValue<U>(nullptr), bool> operator==(Base<T> const &, U const &) {
    std::cout << "operator==(Base, U)" << std::endl;
    return true;
}

template <class U, class T>
std::enable_if_t<EnableComparisonWithValue<U>(nullptr), bool> operator==(U const &, Base<T> const &) {
    std::cout << "operator==(U, Base)" << std::endl;
    return true;
}

int main() {
    Base<int> b1, b2;
    Derived d1, d2;
    b1 == b2; // Compiles fine
    b1 == 42; // gcc and clang compile, msvc does not
    d1 == d2;
    d1 == b1;
    b2 == d2;
    d1 == 42;
    42 == d2;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM