Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ template specialization/overloading

First of all, I'm sorry for the vague title of this question. I wasn't sure how to summarize it.

The thing I want to achieve is the following, I want to be able to pass template non-type parameters of different types to the same class-template, resulting in different instantiations. Something like this:

Foo<1>();
Foo<'1'>(); // different types of object

I don't think this is possible, therefore I'm forced to do something like this

template <typename T, T Val>
struct Foo;

template <int Val>
struct Foo<int, Val> 
{};

template <char Val>
struct Foo<char, Val>
{};

//...

Foo<int, 1>();
Foo<char, '1'>();

such that Foo can be specialized based upon the first template parameter. However this complicates the syntax of the mini-language I'm trying to implement in my metaprogramming framework. Is there any technique available that allows me to distinguish Foo<1> from Foo<'1'>? Basically what I want to do is set a compile-time flag (in an enum) to indicate wheter an int or char was passed, without explicitly specifying them.

EDIT The answers made me realize that my question implicates that I actually need (compile-time) instances of these objects. I don't...

Say that somehow the standard would permit me to overload a class template such that Foo<1> and Foo<'1'> are different types, and contain different values for their flag field. These types can then themselves be passed to another class template, which can inspect them and do interesting stuff with it, for example:

template <typename FooType>
struct Bar
{
    typedef typename If < FooType::flag, int, char >::Type Type;
};

This is all very easy to do when you have nothing against passing the type explicitly, but this seems superfluous...

like image 422
JorenHeit Avatar asked Jan 10 '14 16:01

JorenHeit


2 Answers

You can use macro:

#define MAKE_FOO(value) \
    Foo<decltype(value), value>()

Actually, I think you need something like widespread function template make_something at compile-time. Unfortunately, I don't know how to implement it.

like image 147
Constructor Avatar answered Sep 18 '22 04:09

Constructor


If you simply need the values available at compile-time but don't actually need them as part of the type, (As in, if you don't need Foo<int, 1> and Foo<int, 2> to be different types) then you can use a constexpr constructor along with a constexpr function to give rise to Foo instances at compile-time.

#define DECLTYPE_AUTO(expr) \
  -> decltype(expr) { return expr; }

template <typename T>
struct Foo {

  constexpr Foo(T t) : value(t) {}

  T value;

};  // Foo

template <typename T>
constexpr auto MakeFoo(T val)
    DECLTYPE_AUTO(Foo<T>(val));

static_assert(MakeFoo(2).value == 2, "");
static_assert(MakeFoo('1').value == '1', "");

int main() {}
like image 39
mpark Avatar answered Sep 19 '22 04:09

mpark