0

I have two add methods, one of them for arithmetic, and one for self-types. Basically, scalar and vector add.

However, I C++ always resolves calls to the vector add method. I don't understand why - specializing the vector-add method with a scalar is invalid. Why does this not invoke SFINAE and simply result in the scalar add being resolved? Is there some way I can fix this?

struct Dimu16
{
quint16 x;
quint16 y;

    template<typename To>
    Dimu16 operator+( const To a )  const   {
        return Dimu16{ (quint16)(x+a), (quint16)(y+a) };
    }

    template<class To>
    Dimu16 operator+( To const& o ) const   {
        static_assert( !std::is_arithmetic<To>::value, "" );
        return Dimu16{ (quint16)(x+o.x), (quint16)(y+o.y) };
    }
};
user41010
  • 91
  • 8
  • 1
    Specializing the second one with a scalar results in `Dimu16 operator+(int const& o ) const` which looks perfectly fine. No substitution error. If you want a substitution error, you have to promote the `static_assert` into something that is substituted. `template>> Dimu16 operator+(To const& o) const`. – Raymond Chen Jan 21 '22 at 02:22
  • Do I have the wrong expectations about what errors affect substitution? The later `(int o).x` is an error. Is that supposed to not affect specialization? – user41010 Jan 21 '22 at 02:42
  • 1
    Yes, it's an error, but it's not a substitution failure. Substitution failure occurs during template parameter inference, which considers function parameters and return types, but not the function body (because the function body may not be visible at the time inference occurs). Your `o.x` is in the body, which is too late. – Raymond Chen Jan 21 '22 at 02:53
  • Thanks! I don't know how to accept your comments as an answer, but you've answered by both my need and misunderstanding. I really appreciate it! – user41010 Jan 21 '22 at 02:54
  • Take a look at this https://stackoverflow.com/questions/16302977/static-assertions-and-sfinae I think it's very close to answering your question. Let me know if it does. – cigien Jan 21 '22 at 03:47

1 Answers1

0

Answer via Raymond Chen's comments:

Specializing the second one with a scalar results in Dimu16 operator+(int const& o ) const which looks perfectly fine. No substitution error. If you want a substitution error, you have to promote the static_assert into something that is substituted. template<class To, typename = std::enable_if_t<!std::is_arithmetic_v>> Dimu16 operator+(To const& o) const

[ My followup question: Do I have the wrong expectations about what errors affect substitution? The later (int o).x is an error. Is that supposed to not affect specialization? ]

Yes, it's an error, but it's not a substitution failure. Substitution failure occurs during template parameter inference, which considers function parameters and return types, but not the function body (because the function body may not be visible at the time inference occurs). Your o.x is in the body, which is too late. –

user41010
  • 91
  • 8