3

I am trying to prune back combinatorial explosion of specializations by passing const-ness transparently through a template parameter:

template <typename Sig>
struct IFoo { virtual Sig operator() = 0; }; // XXX, but OK with non-templated aliases...

The compilers are treating Sig as a non-function type before instantiation, so I think I am just looking for a way to coerce the system out of that early belief about the type. Is this not possible, or have I just not stumbled across the correct grammar yet?

I explicitly want to avoid the usual style of specialization-induced deduction:

template <typename Sig> struct IFoo;

template <typename R, typename... Args>
struct IFoo<R(Args...)> { virtual R operator()(Args...) = 0; };

template <typename R, typename... Args>
struct IFoo<R(Args...) const> { virtual R operator()(Args...) const = 0; };

Alternately, is there anything available for const along the lines of the noexcept extraction made available in C++17?

template <typename Sig> struct IBar;

template <typename R, typename... Args, bool IsNoExcept>
struct IBar<R(Args...) noexcept(IsNoExcept)> {
    virtual R operator()(Args...) noexcept(IsNoExcept) = 0;
};

I am unfortunately stuck in C++14, but AFAIK there is no magic if constexpr equivalent in C++17 that is usable from within class definition scope anyway.

Jeff
  • 3,475
  • 4
  • 26
  • 35
  • 2
    [Related](https://stackoverflow.com/questions/47473986/declaring-a-member-function-with-a-typedef-coming-from-a-metafunction), possibly a reverse-duplicate. – Quentin Feb 05 '19 at 14:43
  • Can you elaborate why the specialization-undiced deduction is to be avoided? – Max Langhof Feb 05 '19 at 14:46
  • 1
    I have no idea if this is any closer to what you want, but for a fixed number of arguments (i.e. non-variadic), [this](https://godbolt.org/z/BAZ28F) would not rely directly on specialization of `IFoo`. But it's still unclear to me what the ultimate goal is here. – Max Langhof Feb 05 '19 at 14:56
  • 2
    So you want `template struct IFoo { virtual Sig operator() = 0; };` to really be something like `template struct IFoo { virtual return_type_of_Sig operator()(argument_types_of_Sig) constness_of_Sig = 0; };`? – NathanOliver Feb 05 '19 at 14:58
  • @NathanOliver Yes, exactly. – Jeff Feb 05 '19 at 15:01
  • 1
    @NathanOliver that's actually what it is already, but there seems to be a special standard rule to stop the madness before it plunges into templates :) – Quentin Feb 05 '19 at 15:01
  • @MaxLanghof The helper trait type you give was my backup plan. My primary goal is readability for a non-trivial templated base class (the real `IFoo` has dozens of other methods and half a dozen template parameters), and I am trying to avoid both of boilerplated specializations and (too a lesser extent) throwing too much SFINAE around the interface. – Jeff Feb 05 '19 at 15:14
  • @MaxLanghof Actually I cannot successfully alias a parameter-pack either, so the type-trait approach may not work either. – Jeff Feb 05 '19 at 15:37
  • @Jeff Yeah, that's why it would only work for the non-variadic case. I don't know how many arguments you have to support at max but you could probably work around it with fixed-length parameter list sizes. But I'm not sure. – Max Langhof Feb 05 '19 at 15:40
  • @MaxLanghof It's a public API, so it really need full generality even more than compactness/readability. I expect to end up with a specialization bonanza until we ever see parameter-pack aliasing or parameterized operators/specifiers added for const/volatile/&& like noexcept(). – Jeff Feb 05 '19 at 16:00
  • I see a problem; if you want a `const` operator when the template type is `const` and a non-`const` operator (only) when the template parameter is non-const, you have that when you define (to make an example) `IFoo const f;`, you have that `f` has a non-const operator but can't use it because is a `const` object. – max66 Feb 05 '19 at 16:02
  • @max66 Yes, that's the point of `const` specifiers on member functions... That's no different than `struct X { int foo(int) const; };`. – Max Langhof Feb 05 '19 at 16:03
  • @MaxLanghof - sure; but isn't clear to me if the OP take in count this point – max66 Feb 05 '19 at 16:05
  • @Max66 If those weren't the semantics I needed, I would not have used const member function qualification in the specialized `IFoo` counter-example. – Jeff Feb 05 '19 at 16:13

0 Answers0