0

I read this article. check if member exists using enable_if I modified the code of Johanness Schaub like this.

//////////////////////////////////////////////////////////////////////////
struct NormalChecker {
    struct general_ {};
    struct special_ : general_ {};
    template<typename> struct int_ { typedef int type; };

    template<typename Lhs>
    void modify(Lhs &&lhs) {
        cout << "modify\r\n";
        modifyNormal(lhs, special_());
    }

    template<typename Lhs, typename int_<decltype(Lhs::normal)>::type = 0>
    void modifyNormal(Lhs &&lhs, special_) {
        cout << "modifyNormal with normal\r\n";
    }

    template<typename Lhs>
    void modifyNormal(Lhs &&lhs, general_) {
        cout << "modifyNormal without normal\r\n";
    }
};

struct DataWithNormal {
    int normal;
};

struct DataWithoutNormal {
};

int main() {
    DataWithNormal with_normal;
    DataWithoutNormal without_normal;

    NormalChecker normalCheckerWithNormal;
    normalCheckerWithNormal.modify(with_normal);
    NormalChecker normalCheckerWithoutNormal;
    normalCheckerWithoutNormal.modify(without_normal);

    return 0;
}

But, it just says "modifyNormal without normal" twice. What am I missed?

P-P
  • 1,670
  • 5
  • 18
  • 35

1 Answers1

3

Lhs is deduced to be a reference type in your example, specifically DataWithNormal&. Reference types don't have a nested normal. One way to get around this is to check Lhs when references are stripped:

decltype(std::remove_reference<Lhs>::type::normal)

Lifting Igor's comment, you can also pretend you have an object, since accessing a member of an object works even with a reference:

decltype(std::declval<Lhs>().normal)
chris
  • 60,560
  • 13
  • 143
  • 205
  • 2
    Perhaps a bit more natural: `decltype(std::declval().normal)` – Igor Tandetnik Feb 07 '18 at 02:38
  • In Visual Studio 2015, template:type::normal)>::type = 0> doesn't work, but template().normal)>::type = 0> works. Thanks. – P-P Feb 07 '18 at 04:47
  • @P-P, Oh, that's interesting. I tested it on both Clang and GCC. I figure when they both agree on something, it's usually correct. Unfortunately, I just noticed a little typo: `:type` instead of `::type`. I fixed that. – chris Feb 07 '18 at 11:42