Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Deduce an integer from a template parameter

39 views
Skip to first unread message

Glen Stark

unread,
May 26, 2015, 3:31:13 PM5/26/15
to
Hi Everyone.

Consider the following:

class A; // some non trivial class.
class B; // another non trivial class.

template<typename T> class Foo
{
public:
// some public stuff usint T.
private:
const int m_code; // integer needed for legacy stuff.
// some private stuff which uses T.
}

I would like to do something like:

Foo<A> f; -> instantiating Foo<A> results in m_code == 5
Foo<B> g; -> instantiating Foo<B> reusults in m_code == 10

In fact, then the m_code could be a constexpr, which might open up
further refactorings.


I figure if I experiment and read around I'll be able to come up with a
solution, but I'm doubtful I'll come up with the most elegant solution,
and I figure one of you could maybe tell me what that is?

Thanks for your help, hope my question was clearly phrased.

Glen
Message has been deleted

Ian Collins

unread,
May 26, 2015, 3:52:35 PM5/26/15
to
Glen Stark wrote:
> Hi Everyone.
>
> Consider the following:
>
> class A; // some non trivial class.
> class B; // another non trivial class.
>
> template<typename T> class Foo
> {
> public:
> // some public stuff usint T.
> private:
> const int m_code; // integer needed for legacy stuff.
> // some private stuff which uses T.
> }
>
> I would like to do something like:
>
> Foo<A> f; -> instantiating Foo<A> results in m_code == 5
> Foo<B> g; -> instantiating Foo<B> reusults in m_code == 10
>
> In fact, then the m_code could be a constexpr, which might open up
> further refactorings.

You could make m_code a static member and specialise:

template<> const int Foo<A>::m_code = 5;
template<> const int Foo<B>::m_code = 10;

--
Ian Collins

Victor Bazarov

unread,
May 26, 2015, 3:57:21 PM5/26/15
to
On 5/26/2015 3:43 PM, Stefan Ram wrote:
> Glen Stark <ma...@glenstark.net> writes:
>> I would like to do something like:
>
> I am not an expert for this topic, here is a wild guess:

Truly wild...

>
> #include <iostream>
> #include <ostream>
>
> class A;
> class B;
>
> template< typename T >struct common {};
> template< typename T >struct C : common< T >{ const int m_code; };
> template<> struct C< A >: common< A >{ const int c = 5; };
> template<> struct C< B >: common< B >{ const int c = 10; };
>
> int main(){ ::std::cout << C< A >{}.c << '\n'; }

There is no need to use inheritance, IMHO. You need some kind of type
traits stuff, specialized for A and B, and use it in Foo:

class A; // some non trivial class.
class B; // another non trivial class.

template<typename T> struct traits_used_by_Foo {
};

template<> struct traits_used_by_Foo<A> {
enum { code = 5 };
};

template<> struct traits_used_by_Foo<B> {
enum { code = 10 };
};

template<typename T> class Foo
{
public:
// some public stuff usint T.
private:
const int m_code = traits_used_by_Foo<T>::code;
// some private stuff which uses T.
};

V
--
I do not respond to top-posted replies, please don't ask

Glen Stark

unread,
May 27, 2015, 2:50:09 AM5/27/15
to
This is the solution that occurred to me, but I will need a different
code for each type I pass as template argument, and I don't want to have
to specialize the constructor for each use. What I'd really like is some
kind of compile-time lookup table.

Type traits (as suggested by Victor) might be my best bet. I gues what I
had hoped for was some kind of templated initializer which takes a type
and returns an integer. Something like:

template <typename T>
Foo<T>::Foo():m_class(template_magic_here<T>)
{
}

Ian Collins

unread,
May 27, 2015, 3:34:30 AM5/27/15
to
You're not specialising a constructor, just a member. This is probably
the least amount of work and you get the added bonus of a link fail if
you try and pass a type you haven't specialised.

You could get want you want (compile-time lookup) with type-lists, but
you probably don't want to go there...

--
Ian Collins
0 new messages