4

I'm trying to check if a class that I'm templating is inheriting from another templated class, but I can't find the correct way to do it.

Right now I have the following:

#include <iostream>

template <typename MemberType, typename InterfaceType>
class Combination : public InterfaceType
{
public:
    Combination();
    virtual ~Combination();

private:

    MemberType*   pointer;
};


class MyInterface {};
class MyMember {};

class MyCombination : public Combination<MyMember, MyInterface>
{

};


int main()
{
    static_assert(std::is_base_of_v<Combination<MyMember, MyInterface>, MyCombination>);
    std::cout << "hello";
}

Which is working fine, but in the place this template is placed, I don't have access to the template parameters definitions, and this should be quite generic. What I'd like is to test for the MyCombination class to inherit from a generic Combination without taking into account the template arguments, something like this:

static_assert(std::is_base_of_v<Combination, MyCombination>);
or
static_assert(std::is_base_of_v<Combination<whatever, whatever>, MyCombination>);

Would you know how to check for this? In this case I can't use boost libraries or other external libraries.

Thanks!

EDIT: I don't have access to modify the Combination class, and what I can change is the assert and the My* classes.

8
  • What is the underlying thing you are trying to solve? Code/implementation reuse? Maybe your issues have more to do with your design directions. (Some ideas here : onlinegdb.com/K0ow4stMv) Commented Jul 19, 2022 at 9:26
  • I am not sure if I understand your problem, static_assert will create a compile time error or not, but does not do anything in the executed code. So, it is not important where in the code it is placed, it does not have to be in main, it can be where you create an object of MyCombination, where MyInterface and MyMember should be known. Commented Jul 19, 2022 at 9:30
  • @PepijnKramer I'm generating a macro for creating a class, and I'd like to check if the user of that class has a correct hierarchy, because I have to access elements from the Combination class, if the user of that class doesn't use the Combination class then I should report the error. The ideas you propose look good, but I can't modify the Combination class (I've just edited the post). Thanks! Commented Jul 19, 2022 at 9:39
  • @mch yes, you're right, I put the assert there because... don't know, I was inspired like that when making the example :P In the official code the assert if just before the declaration of the template, inside a macro for generating the class. The problem in the official code is that I shouldn't have access to MyInterface and MyMember, as it's a very generic place. Thanks for the comment :) Commented Jul 19, 2022 at 9:41
  • Does this answer your question? checking if a class inherits from any template instantiation of a template Commented Jul 19, 2022 at 9:41

1 Answer 1

3

This can easily be done with the C++20 concepts. Note that it requires a derived class to have exactly one public instantiated base class.

template <typename, typename InterfaceType>
class Combination : public InterfaceType {};

class MyInterface {};
class MyMember {};

class MyCombination : public Combination<MyMember, MyInterface> {};

template<class Derived, template<class...> class Base>
concept derived_from_template = requires (Derived& d) {
  []<typename... Ts>(Base<Ts...>&) {}(d);
};

static_assert(derived_from_template<MyCombination, Combination>);

Demo

The equivalent C++17 alternative would be

#include <type_traits>

template<template<class...> class Base, typename... Ts>
void test(Base<Ts...>&);

template<template<class...> class, class, class = void>
constexpr bool is_template_base_of = false;

template<template<class...> class Base, class Derived>
constexpr bool is_template_base_of<Base, Derived, 
  std::void_t<decltype(test<Base>(std::declval<Derived&>()))>> = true;

static_assert(is_template_base_of<Combination, MyCombination>);
Sign up to request clarification or add additional context in comments.

7 Comments

Woah nice! It works perfectly! Would you know how to do it without C++20, I may be limited to C++17 or C++14.
Is it possible to make this work with both regular and non-type template parameters?
Also, is it possible to use this with some of the template parameters being specified and only the remaining leaving unspecified? E.g., with Base<T, U, V>, can I check if Derived is derived from Base<int, int, V> where only the first two parameters are specified?
@MichaelSchlottke-Lakemper I believe that is feasible.
@康桓瑋 would you know how to do this and willing to answer it if I posted a question about it 😬
|

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.