Ограничение компилятора MSVC C ++ - черта не работает под CRTP - PullRequest
3 голосов
/ 21 мая 2019

У меня проблема с MSVC 2017 и 2019 по поводу этого ограничения: я хотел бы знать во время компиляции, имеет ли определенный класс «производных» шаблонов CRTP определенную функцию.

Я получил это как свой классоценка черты:

template <typename T>
class function_exists_trait
{
private:
    template <typename U>
    static auto test_todo(U * u) -> decltype(&U::exists) {}
    static auto test_todo(...) -> std::false_type {}

public:
    static constexpr bool value{ !std::is_same<decltype(test_todo(static_cast<T*>(nullptr))), std::false_type>::value };
};

Я проверил это с несколькими тривиальными классами:

struct t1 { void exists() {} };
struct t2 { void exists() {} };
struct t3 {};
struct t4 : public t1 {};
struct t5 : public t3 {};
struct t6 : public t3 { void exists() {} };

Я получил ожидаемые результаты.Как и ожидалось, оценки дают: 1 1 0 1 0 1 с этим тестом: cout << function_exists_trait<t1>::value << " " << ...

Я получил ожидаемые результаты для следующих простых реализаций CRTP (0 1 1 1):

template <typename t> struct u1 {};
struct crtp1 : public u1<crtp1> { void exists() {} };
template <typename t> struct u2 { void exists() {} };
struct crtp2 : public u2<crtp2> {};

cout << function_exists_trait<u1<int>>::value << " "
     << function_exists_trait<crtp1>::value << " "
     << function_exists_trait<u2<int>>::value << " "
     << function_exists_trait<crtp2>::value << endl;

Проблема заключается в следующем: при попытке оценить черту внутри базового класса CRTP ничего не работает, и я не понимаю, почему.

template <typename t> struct u3 { 
    static inline constexpr bool value{ function_exists_trait<t>::value }; 
};
struct crtp3 : public u3<crtp3> { void exists() {} };

template <typename t> struct u4 { 
    void exists() {}
    static inline constexpr bool value{ function_exists_trait<t>::value };
};
struct crtp4 : public u4<crtp4> {};

template <typename t> struct u5 {
    void exists() {}
    static inline constexpr bool value{ function_exists_trait<t>::value };
};
struct crtp5 : public u5<crtp5> {
    void exists() {}
};

Следующий код дает такой результат: 0 0 -0 0 - 0 0 - 0 0

cout << function_exists_trait<u3<int>>::value << " " << u3<int>::value << " - "
        << function_exists_trait<crtp3>::value << " " << crtp3::value << " - " 
        << function_exists_trait<crtp4>::value << " " << crtp4::value << " - "
        << function_exists_trait<crtp5>::value << " " << crtp5::value << endl;

Я опубликовал эту проблему, думая, что я что-то делал не так, но, похоже, проблема с MSVC.Спасибо PW, который показал мне, что это ограничение MSVC.Он показал мне, что точно такой же код дает этот результат в gcc: 0 0 - 1 1 - 1 1 - 1 1

У кого-нибудь есть предложения, как решить эту проблему.Возможно, есть очевидное решение с MSVC, чтобы вызвать ожидаемый результат.Или просто другой способ достижения той же цели в MSVC.

1 Ответ

1 голос
/ 23 мая 2019

Как выяснил Богдан, это рабочая альтернатива:

template <typename t> struct u6 {
    void exists() {}
    static constexpr bool value() { return function_exists_trait<t>::value; }
};
struct crtp6 : public u6<crtp6> {
    void exists() {}
};

Спасибо всем!

...