user4085386
user4085386

Reputation:

How to compile-time condition on template typename?

Suppose I have a class A template as follows:

template<typename T>
class A
{
    T data;
public:
    void func(){} //concerned function ** see here **
};

Now I have another class B template, say as

template<typename U>
class B
{
    // ... something whatever
};

That means the condition for not constructing the function is that the immediate template typename T is B. And C can be any type including A and B.

Upvotes: 0

Views: 943

Answers (2)

  1. Member functions of class templates aren't generated unless they are odr-used. This is part of the mechanism's strength.

  2. If you want to constrain the use of this member function, then you would indeed use std::is_same. The trick is to define the appropriate trait/meta-function:

    template<class, template<class...> class>
    struct is_template_instance : std::false_type {};
    
    template<template<class...> class T, class... Cs>
    struct is_template_instance<T<Cs...>, T> : std::true_type {};
    

    The true specialization will only be chosen for something like is_template_instance<std::vector<int>, std::vector>. Now just put it to use, either static assert or std::enable_if:

    auto func() ->
      typename std::enable_if<!is_template_instance<T, B>::value>::type {
    }
    

Upvotes: 2

Rakete1111
Rakete1111

Reputation: 49028

You need to partial specialize the template:

template<typename C>
class A<B<C>> // Used when A<B<C>> is instantiated
{
    B<C> data;
};

The only downside on this is that this requires some code duplication, which is not always possible.

Instead, you can create a base class with all the functionality, and derived from that base:

// Base class with all the common functionality.
template<typename T>
class A_impl
{
protected:
    T data;
};

// Special case when 'func' is available.
template<typename T>
class A : public A_impl<T>
{
public:
    void func() {}
};

// Another special case where 'func' is not available.
template<typename C>
class A<B<C>> : public A_impl<B<C>> {
};

Upvotes: 1

Related Questions