2

I'm struggling to make this code work

template <typename T, typename U = int, auto... Params>
class Foo {};

int main()
{
    auto foo1 = Foo<int, int, 1, 2, 3>{};
    auto foo2 = Foo<int, 1, 2, 3>{}; // I want it to compile
}

It looks like I need some hack. I tried partial specialization, but it doesn't work either

template <typename T, typename U, auto... Params>
class Foo {};

template <typename T, auto... Params>
class Foo<T, int, Params...> {};

int main()
{
    auto foo1 = Foo<int, int, 1, 2, 3>{};
    auto foo2 = Foo<int, 1, 2, 3>{}; // I want it to compile
}

I can't find anything closely related to this, help pls :)

6
  • This looks weird, what are you actually trying to do here? Please show a representative implementation of Foo. Commented Aug 9, 2022 at 23:01
  • The closest I could get so far is Foo<list<int, int>, 1, 2, 3>. Commented Aug 9, 2022 at 23:05
  • @PaulSanders, actually, I'm trying to write constrained_type - a class, which applies set of predicates to the contained value. The value itself contains in an optional. I want to parametrize over different kids of optionals (for example std::optional and compact_optional) Source code can be viewed here: Commented Aug 9, 2022 at 23:07
  • I think this can't be done. The problem can be deduced to this: struct A {} A;. This means that A can be a type when a type is expected by the parser, but it can also be a value when a value is expected by the parser. So it's the calling code that must resolve whether something is a type or a value. In your case, this is undecided. Commented Aug 9, 2022 at 23:12
  • @lorro, if this is true - it's so stupid, that compiler cannot differentiate between type and non-type parameters Commented Aug 9, 2022 at 23:16

1 Answer 1

0

Unfortunately due to the way that template deduction works, this is ...not going to work.

Here's one alternative approach where the first template parameter is always a tuple, with one or two types, with the second type defaulting to an int:

#include <tuple>

template<typename T, auto ...Params> class Foo;

template<typename T, typename U, auto ...Params>
class Foo< std::tuple<T, U>, Params...> {

    // Your template goes here, making use of T and U
};

template<typename T, auto ...Params>
class Foo< std::tuple<T>, Params...> : Foo<std::tuple<T, int>, Params...> {

    // Might need to define some cleanups here, like a delegating constructor,
    // and/or delegated overload operators.

};

Foo<std::tuple<char>, 3, 4> defaulted;

Foo<std::tuple<char, float>, 3, 4> non_defaulted;

With a little bit more elbow grease it should be possible to require a formal std::tuple only when the 2nd optional type needs to be specified, and just specify the primary type directly (although that will create some avoidable confusion if the primary type is a std::tuple, itself).

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.