Reputation: 14356
Suppose I have a simple template class:
template <typename ElementType, ElementType Element>
class ConsecutiveMatcher
{
public:
bool operator () (ElementType lhs, ElementType rhs)
{
return lhs == Element && rhs == Element;
}
};
I would usually make instantiation simpler than ConsecutiveMatcher<wchar_t, L'\\'>()
by providing a function which can infer the template argument types based on the parameter types:
template <typename ElementType>
ConsecutiveMatcher<ElementType, Element /* ?? */>
MakeConsMatcher(ElementType Element)
{
return ConsecutiveMatcher<ElementType, Element>();
}
However, in this case, MakeConsMatcher(L'\\')
will not work, because the function needs to return a class whose template does not only contain a type, but also a value.
How can I return a class template from a function which has not only type template arguments, but also value template arguments?
Upvotes: 0
Views: 1337
Reputation: 13005
I'm just looking for a way to omit the wchar_t and use automatic type deduction during instantiation.
I can imagine such situations:
Argument type only known at runtime (and you have no any idea about it): you cannot handle it with templates: you will want to redesign your code and use inheritance and virtual functions (or, probably, mix both, templates and inheritance)
Argument type known at compile-time, argument value known at runtime: left Type of argument in template argument list and pass argument value to constructor, then, for user's convenience, make factory function to deduce type
template<typename T>
struct MyType
{
template <class T>
MyType(const T& defaultValue) :
value(defaultValue)
{}
T value;
};
template<typename T>
MyType<T> MyFactory(const T& defaultValue)
{
return MyType<T>(defaultValue);
}
int main()
{
char c = 'a';
wchar_t w = L'a';
int i = 42;
float f = 3.14f;
auto mt_char = MyFactory(c);
auto mt_wchar = MyFactory(w);
auto mt_int = MyFactory(i);
auto mt_float = MyFactory(f);
}
At compile-time you know a list of Types and want they behave differently (for example have different default values): make template specializations for each type from a list, then, for user's convenience, create typedefs
template<typename T> struct MyType
{
MyType(const T& defaultValue) :
value(defaultValue)
{}
T value;
};
template<>
struct MyType <char>
{
MyType() :
value('c')
{}
char value;
};
template<>
struct MyType <wchar_t>
{
MyType() :
value(L'w')
{}
wchar_t value;
};
typedef MyType<char> MyTypeChar;
typedef MyType<wchar_t> MyTypeWchar;
int main()
{
MyTypeChar mt_char_default;
MyTypeWchar mt_wchar_default;
}
In this case, user still can instantiate own specializations. Example of that approach is a std::basic_string
class.
Further, you can simplify your specializations, if make class members static
or static const
and for integral types just define in member list:
template<>
struct MyType <char>
{
static const char value = 'c';
};
Upvotes: 1
Reputation: 146
You want a runtime computed value turned into an template argument? it's not possible.
Upvotes: 1