Reputation: 71
I have a class template like this:
template <typename T1, typename T2>
class ClassName {
// Members variables and Functions based on the template parameter types
};
(T1, T2)
can either be (class A, class B)
or (class C, class D)
only.
So, T1 alone is enough to determine T2.
Is there any way to only take T1 as a parameter and write the same class? If yes, how?
Upvotes: 0
Views: 112
Reputation: 122133
If your template only depends on a single parameter, you should not declare it with 2 parameters. You can use std::conditional
together with std::is_same
to declare conditional aliases.
If you want:
(T1, T2) can either be (class A, class B) or (class C, class D) only
If "only" is meant as: User only ever instantiates for A
or C
and in that case T2
should be B
/ D
:
#include <type_traits>
struct A {};
struct B {};
struct D {};
template <typename T>
struct Foo {
using T1 = T;
using T2 = std::conditional_t<std::is_same_v<A, T>, B, D>;
};
Foo<A>::T2
is B
and Foo<C>::T2
is D
. Actually Foo<T>::T2
is D
for any T
that is not A
. In other words, as mentioned above, the premise is that it is only instantiated for either A
or C
. If the template itself should make sure that only instantiations for A
or C
are valid, you might want to add a static_assert
(again using std::is_same
to check that T
is among the allowed types).
Upvotes: 5
Reputation: 12749
You can write a type trait:
#include <iostream>
#include <type_traits>
struct A {};
struct B {};
struct C {};
struct D {};
template <typename Type> struct Dependent {};
template<>
struct Dependent<A> {
using type = B;
};
template<>
struct Dependent<C> {
using type = D;
};
template <typename Type>
class ClassName {
using Dependent = typename Dependent<Type>::type;
};
int main()
{
static_assert(std::is_same<Dependent<A>::type, B>::value, "");
static_assert(std::is_same<Dependent<C>::type, D>::value, "");
// Dependent<B>::type a; error: 'type' is not a member of 'Dependent<B>'
}
Upvotes: 3
Reputation: 66912
Make an enumeration of your configurations:
enum class ClassConfigEnum { AB, CD};
template<ClassConfigEnum config> struct ClassConfig;
template<> struct ClassConfig<AB> {
using T1 = A;
using T2 = B;
};
template<> struct ClassConfig<CD> {
using T1 = C;
using T2 = D;
};
And then have the class use the enumerated configuration
template <ClassConfigEnum config>
class ClassName {
using T1 = ClassConfig<config>::typename T1;
using T2 = ClassConfig<config>::typename T2;
};
Upvotes: 4