Template parameters dilemma - c++

I have a dilemma. Suppose I have a template class:
template <typename ValueT>
class Array
{
public:
typedef ValueT ValueType;
ValueType& GetValue()
{
...
}
};
Now I want to define a function that receives a reference to the class and calls the function GetValue(). I usually consider the following two ways:
Method 1:
template <typename ValueType>
void DoGetValue(Array<ValueType>& arr)
{
ValueType value = arr.GetValue();
...
}
Method 2:
template <typename ArrayType>
void DoGetValue(ArrayType& arr)
{
typename ArrayType::ValueType value = arr.GetValue();
...
}
There is almost no difference between the two methods. Even calling both functions will look exactly the same:
int main()
{
Array<int> arr;
DoGetValue(arr);
}
Now, which of the two is the best? I can think of some cons and pros:
Method 1 pros:
The parameter is a real class not a template, so it is easier for the user to understand the interface - it is very explicit that the parameter has to be Array. In method 2 you can guess it only from the name. We use ValueType in the function so it is more clear this way than when it is hidden inside Array and must be accessed using the scope operator.
In addition the typename keyword might be confusing for many non template savvy programmers.
Method 2 pros:
This function is more "true" to its purpose. When I think if it, I don't really need the class to be Array. What I really need is a class that has a method GetValue and a type ValueType. That's all. That is, this method is more generic.
This method is also less dependent on the changes in Array class. What if the template parameters of Array are changed? Why should it affect DoGetValue? It doesn't really care how Array is defined.
Evey time I have this situation I'm not sure what to choose. What is your choice?

The second one is better. In your "pros" for the first one, you say, "it is very explicit that the parameter has to be Array". But saying that the parameter has to be an Array is an unnecessary limitation. In the second example, any class with a suitable GetValue function will do. Since it's an unnecessary limitation, it's better to remove it (second one) than to make it explicit (first one). You'll write more flexible templates, which is useful in future when you want to get a value from something that isn't an Array.

If your function is very specific to ArrayType, and no other template will satisfy its interface requirements, use #1 as it's both shorter and more specific: the casual reader is informed that it operates on an ArrayType.
If there's a possibility that other templates will be compatible with DoGetValue, use #2 as it's more generic.
But no use obsessing, since it's easy enough to convert between them.

My friend proposed two more, somewhat more extreme, methods:
Method 3: gives you the ability of using types that don't have a ::ValueType.
template <typename ArrayType, typename ValueType = ArrayType::ValueType>
void DoGetValue(ArrayType& arr)
{
ValueType value = arr.GetValue();
...
}
Method 4: a cool way of forcing the array to be a class that has one template parameter.
template <template <typename> class ArrayType, typename ValueType>
void DoGetValue(ArrayType<ValueType>& arr)
{
ValueType value = arr.GetValue();
...
}

Related

How to access the template argument's own template arguments?

Say you have a class template (e.g. second below). Say that class template's template arguments are instantiations of another class template (e.g. first below). How do you access the template argument's own template arguments? Is that possible?
Here's some code:
template<size_t n>
class first {
};
template<typename instantiated_first>
class second {
// would like to be able to access the "n"
// of instantiated_first
};
int main() {
second<first<3>> thing;
return 0;
}
Three possibilities come to mind:
rewrite first to store n as a data member, or
redesign second to inherit from an instantiated class from first, and
ask for the exact same template arguments in both class templates.
I ask because I would rather not edit pre-existing code (option 1), and in my particular application, it doesn't really make sense (to me, at least) to think of second as being a type of first (option 2). I will be instantiating many objects of type specialized_first, and so it makes more sense for second to "own" these objects and store them in a container. Option 3 doesn't seem very stylish, either.
Are there any fancy template features that I don't know about to accomplish this in a nice way?
The more sensible way is not to store n as a data member but rather as static constexpr size_t so it doesn't allocate any additional runtime space. This is the standard and most flexible mechanism - allowing for various other templates to access this parameter without mush fuss. E.g., you can make a completely different version of first and allow your second to utilize the other version all the while supporting the original as long as all version satisfy the concept interface.
Similarly, every typename T_ template parameter can be forwarded to users of the template via using T = T_;. In general, template parameters are inaccessible unless you allow them to be by declaring them to be types or storing their value as constexpr or otherwise.
You can remodel second so it accepts the same template parameter but it becomes harder the more other templates you have that use first and this value/type or when you suddenly want to use second for an alternative version of first. Better address such problems on the root. For example, in std all their template classes have all the necessary types declared inside the class in a similar manner.
You declare a partial specialization and pick the arguments from there.
template<typename T>
class second<first<T>> {
// T is available here for use.
};
Or even more generally do this
template<typename T, typename U
class second<U<T>> {
// T is available here for use.
};
This will match all instantiations with one template argument.

C++ template specialization all types except one

I need a method(C++ 11) that is called for all types except one.
template<typename T>
void method(T& value)
{
...
}
template<>
void method(std::string& value)
{
...
}
Is it possible to do something like this? If not, is there other alternatives than using typeid at runtime?
there are several ways to do this, so you can use most convenient one:
// way 1
template<typename T,
typename std::enable_if<!std::is_same<T,std::string>::value>::type* = nullptr>
// way 2
void method(T& value)
{
static_assert(!std::is_same<T,std::string>::value,"std::string is not accepted");
...
}
// way 3
template <>
void method<std::string>(std::string&) = delete;
As for me, I find 3 to be the most convenient one for filtering out specific type, and 1 for filtering out some subset of types
You do not need template specialization. And neither SFINAE (enable_if). When you get caught up in template functions it's easy to forget that functions can overload. Just create a non-templated overload and that will be preffered when passing an argument of that exact type (a better solution is presented in the linked article):
template<typename T>
void method(T& value)
{
// ...
}
void method(std::string& value)
{
// ...
}
I strongly recommend reading this article Why Not Specialize Function Templates? by Herb Sutter.
Moral #1: If you want to customize a function base template and want
that customization to participate in overload resolution (or, to
always be used in the case of exact match), make it a plain old
function, not a specialization. And, if you do provide overloads,
avoid also providing specializations.
But you fall in the Moral #2:
But what if you're the one who's writing, not just using, a function
template? Can you do better and avoid this (and other) problem(s) up
front, for yourself and for your users? Indeed you can:
Moral #2: If you're writing a function base template, prefer to
write it as a single function template that should never be
specialized or overloaded, and then implement the function template
entirely as a simple handoff to a class template containing a static
function with the same signature. Everyone can specialize that -- both
fully and partially, and without affecting the results of overload
resolution.
The whole explanation is in the article.
This is basic template specialization, look at code sample below.
Code sample (based on your code):
template<typename T>
void method(T& value) {
//
}
template<>
void method<std::string>(std::string& value) {
//
}
This means, when you call method with std::string parameter the second (specialized) method will be called. Otherwise if you do not want to have the second function, then you will have to use c++ type traits (answered in the other answer).

Type erasure and variadic templated member function

The example below is a minimal, maybe not so good example of a well known idiom.
It compiles and it is so ugly in order to be able to maintain it minimal, because the question is not about the idiom itself.
struct Foo {
virtual void fn() = 0;
};
template<class T>
struct Bar: public Foo {
void fn() override {
T{}.fn();
}
};
struct S {
void fn() { }
};
int main() {
Foo *foo = new Bar<S>{};
foo->fn();
}
What I'm struggling with since an hour ago is how to change it (or even, if there exists an alternative idiom) to introduce a variadic template member method.
Obviously, I cannot modify the fn function of the Foo class, because it's a virtual one and virtual specifier doesn't goes along with templates. The same is valid for the fn specification of Bar, because it has to override somehow the one in the base class.
Note.
For I strongly suspect that this question could be one of the greatest XYProblem ever seen, I'd like also to give a brief description of the actual problem.
I have a class that exposes two templated member methods:
the first one accepts a template class T that is not used immediately, instead it should be stored somehow in order to be used later.
the second one accepts a variadic number of arguments (it is actually a variadic templated member function) and those arguments should be perfectly forwarded to a newly created instance of T.
Well, the problem is far more complex, but this is a good approximation of it and should give you an idea of what's the goal.
Edit
I guess that it is somehow similar to higher order functions.
I mean, what would solve the problem is indeed a templated function to which to bind the first argument, but as far as I know this is impossible as well as any other approach I've explored so far.
Any viable solution that expresses the same concept?
What I mentioned in the comments is the following approach:
template<typename T> class Factory {
public:
template<typename ...Args>
auto construct(Args && ...args)
{
return T(std::forward<Args>(args)...);
}
};
So now, your first exposed class method will be something like this:
template<typename T>
auto getFactory() {
return Factory<T>();
}
So:
auto factory=object.getFactory<someClass>();
// Then later:
factory.construct(std::string("Foo"), bar()); // And so on...
Instead of construct() you could use operator() too, so the second part of this becomes, simply:
factory(std::string("Foo"), bar()); // And so on...
As I mentioned, this is not really type erasure. You can't use type erasure here.
Having given this a few minutes' more thought, the reason that type erasure cannot be used here is because a given instance of type erasure must be "self contained", or atomic, and what you need to do is to break atomic type erasure into two parts, or two class methods, in your case.
That won't work. Type erasure, by definition, takes a type and "erases" it. Once your first function type-erases its class method template parameter, what you end up with is an opaque, type-erased object of some kind. What was type-erased is no longer available, to the outside world. But you still haven't type-erased your constructor parameters, which occurs somewhere else.
You can type-erase the template class, and the constructor parameters together. You can't type-erase the template class, and the constructor parameters, separately and then somehow type-erase the result again.
The simple factory-based approach, like the one I've outlined, would be the closest you can get to results that are similar to type erasure, if both halfs of your desired type-erasure appear in the same scope, so you can actually avoid type-erasure, and instead rely on compiler-generated bloat.
I also agree that you cannot do exactly what you want here. I will post what I think the closest option is (at least a close option that is different from SamVarshavchik's answer).
I don't expect this answer to solve your problem exactly, but hopefully it will give you some ideas.
struct Delay // I have no idea what to call this
{
template <class T>
void SetT()
{
function_ = [](boost::any params){return T(params);}
}
template <class ... Args>
boost::any GetT(Args ... args)
{
return function_(std::make_tuple(args...));
}
private:
std::function<boost::any(boost::any)> function_;
};
The obvious limitation of this is that anyone calling GetT will somehow have to know what T was already, though you can query the boost::any object for the type_info of its class if that helps. The other limitation here is that you have to pass in T's that take a boost::any object and know what to do with it. If you cannot have T do that, then you can change SetT (or create a new member function) like this:
template <class F>
SetTFactory(F f)
{
function_ = f;
}
and then use it like:
Delay d;
d.SetTFactory([](boost::any s){return std::string(boost::any_cast<const char*>(s));});
auto s = d.GetT("Message");
assert(s.type() == typeid(std::string));
This of course introduces a whole new set of difficulties to deal with, so I don't know how viable this solution will be for you. I think regardless of anything else, you're going to have to rethink your design quite a bit.

Could this templated syntax be improved?

I have this template method:
template <class SomeLhs, class SomeRhs,
ResultType (SomeLhs::*callback)(SomeRhs&)>
void Add() {
struct Local {
static ResultType Trampoline(BaseLhs& lhs, BaseRhs& rhs) {
return (static_cast<SomeLhs&>(lhs).*callback)(static_cast<SomeRhs&>(rhs));
}
};
_back_end.template Add<SomeLhs,SomeRhs>(&Local::Trampoline);
}
Currently I'm calling it like this:
tracker.Add<Quad, Multi, &Quad::track>();
tracker.Add<Quad, Singl, &Quad::track>();
tracker.Add<Sext, Multi, &Sext::track>();
...
It is working fine, but I don't like to have to repeat two times the name of class SomeLhs. Is there a way to avoid that?
For people who may have recognized it: yes, this is related to the BasicFastDispatcher of Alexandrescu, in particular I'm writing a front end to operate with member functions.
I don't think it can't be improved particularly, which is unfortunate as I'd love to find a way to do this.
Template type deduction is only possible for function template arguments and you need to pass in the non-type member function pointer at compile time in order for it to be treated as a name rather than a varying quantity. Which means having to specify all the args.
i.e. you can do this:
template <class SomeLhs, class SomeRhs>
void Add(ResultType (SomeLhs::*callback)(SomeRhs&)) {
...
}
// nice syntax:
tracker.Add(&Sext::track);
// But ugly for overloaded functions, a cast is needed.
// p.s. not sure this is exactly the right syntax without compiling it.
tracker.Add((ResultType (Quad::*)(Multi&) &Quad::track);
But then you have an actual pointer that cannot subsequently be used as a template parameter.
The only thing I think you could do is to use a macro, though it is arguable if it really improves syntax here. I'd say it probably adds an unnecessary level of obfuscation.
e.g.
#define TMFN_ARGS(C, M, P1) C, P1, &C::M
tracker.Add<TMFN_ARGS(Quad, track, Multi)>();
EDIT:
However, if the name of the function is Always 'track', you could do something along the following lines:
template <typename C, typename P1>
void AddTrack() {
Add<C, P1, &C::track>();
}
tracker.AddTrack<Quad, Multi>();

Implementing a C++ hashtable class using template

I am trying to implement a hashtable in C++ that sort of like the Java version
I would like it has the form of
template <class Key, class Value>
class hashtable {
...
}
Soon enough I notice that I need to somehow convert Key into a number, so that I can use the simple hash function
int h(int hashkey) {
return hashkey%some_prime;
}
But the headache is, Key type is only known at run time. Is it possible to check what type Key is on run time in C++. Or I have to create this hashtable class with different type manually? That is easier to do but ugly. Anyone know an elegant solution?
C++ templates are usually duck typed, meaning that you can explicitly cast to an integeral type in the template, and all types that implement the appropriate conversion can be used as a key. That has the disadvantage of requiring that the classes implement the conversion operator in such a fashion that the hash function will be decent, which is asking for a lot.
You could instead provide a function template
template<typename T> int hash (T t);
Along with specializations for the built in types, and any user that wants to use a custom class as key will just have to provide his own specialzation. I think this is a decent approach.
You seem to have a few misunderstandings. Key type is known at compile time - that's the whole point of using templates. Secondly, there is really no such thing as a completely generic hash function that will work on any type. You need to implement different hash functions for different types, using function overloading or template specialization. There are many common hash functions used for strings, for example.
Finally, C++11 includes a standard hash table (std::unordered_map) which you can use instead of implementing your own.
If you would like try to implement a "generic" one, perhaps you can start with a skeleton much like this:
template <class T, class K>
struct HashEntry { // you would need this to deal with collision
T curr;
K next;
}
template <class V, size_t n>
class HashTable {
void insert(V v)
{
...
size_t idx = v->getHashCode(n);
...
}
private:
HashEntry <V> table_[n];
}
It is usually instantiated with some pointer type, to figure out where a pointer should go, it requires the type implement member function "getHashCode" ...