C++ template specialization/overloading

无人久伴 提交于 2019-12-23 09:32:15

问题


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...


回答1:


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.




回答2:


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() {}



回答3:


You could do something like this:

template <int Val>
struct Foo<int, Val> 
{
    static MyEnum tag = myTag1;
};


template <char Val>
struct Foo<char, Val>
{
    static MyEnum tag = myTag2;
};


来源:https://stackoverflow.com/questions/21049359/c-template-specialization-overloading

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!