问题
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