Could this templated syntax be improved? - c++

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>();

Related

Unknown return type of template functions, code repetition when using decltype

In my job, there are several template mathematical classes (e.g matrix).
An object can be implemented using either floats or doubles (or other numerical types but for this matter, it doesn't really matter).
A double object can only interact with another double object. For this matter the function convert() was implemented for various types, with an implementation similar to this:
Matrix<T2> convert(const Matrix<T1>& m, T2 dummy) {
// create a matrix with type T2 and cast m values into it
// retMatrix(i, j) = (T2)m(i,j)
}
You would call it with:
auto floatMatrix = convert(doubleMatrix, 0.f);
Or the slightly more verbose:
auto floatMatrix = convert(doubleMatrix, float());
I want to add a function like the one below that will enable a cleaner (IMHO) way to call these functions
template <typename T, typename S>
auto convert(S&& s) -> decltype(convert(s, T())) {
return convert(s, T());
}
Now they can be called using:
auto floatMatrix = convert<float>(doubleMatrix);
My question is that my function signature is pretty awkward, I need to repeat the convert(s, T()) both in the decltype and in the actual function body
How do I overcome this?
thanks
edit:
currently, we are not using c++14
edit #2:
the Matrix class was just an example, there are quite a few relevant classes that have the convert() function implemented for them. Each of them already "specialized" like someone suggested in an answer below (deleted meanwhile). I would like to adjust the way convert() is called without re implementing everything
edit #3:
supported types are obviously other than only float and double. please treat the example I gave as an example and not the actual problem I'm trying to solve
the "dummy" functions are already implemented, I was trying to make it work with minimal effort, instead of refactoring 30 functions and all usages
I don't think the question is so far fetched considering cpp14 allows to just remove the -> decltype() thingy...
A little confusing why the need for templates in the first place instead of function overloading:
Matrix<double> convert(const Matrix<float>& m) {
// ...
}
Matrix<float> convert(const Matrix<double>& m) {
// ...
}
float->float and double->double don't seem like meaningful operations that need to be preserved so actually making that a compiler error seems beneficial (whereas the template mechanism might actually succeed and just create an unnecessary copy).
Also the need for the dummy parameter in the first place is confusing without a more complete example.
If you're set on templates (e.g. types go beyond just these two):
template <typename T2, typename T1>
Matrix<T2> convert(const Matrix<T1>& m) {
}
If you're trying to write 1 single generic conversion function across all your other conversion functions you have no way of simplifying what you wrote until C++14 (I mean there are other ways to write it but it seems unlikely to be simpler).
One option might be helper classes that know the conversion type from Matrix for T to Matrix, but they are no prettier than the decltype statement, which is readable and local to the code.
Could Matrix derive from a base class that knows how to generate Matrix from T? Perhaps as a member so you can write:
class MatrixBase
{
public:
template <class T> class To
{ typedef Matrix<T> To; };
};
class Matrix<int>:public MatrixBase {
// ...
};
All this just to write: -> S::To<T>::To
As you say, come the C++14 revolution you can do the fully automatic return type thing.

Combining templates and type safety

Let's say I have several functions defined like this:
template <typename T>
inline void read<bool>(T **data) {
//some code
}
template <typename T>
inline void read<double>(T **data) {
//some other code
}
template <typename T>
inline void read<int>(T **data) {
//also different code
}
Now, I create another function defined like this:
template<typename T>
inline void readMultiple(T **data, int counter) {
for (int i = 0; i < counter, ++i) {
read<T>(data);
}
}
(1)That would call the appropriate read<T>(T **data) implementation based on the type T, right?
(2)If I were to specify a type that is not one of the three above, I'd get a compilation error, since that function is not defined, right?
(3)Also, can I make this call:
double **d;
read<double>(d);
to ensure that I called the implementation for double?
I know I'd get the same result without the <double> part, but this way I'm ensuring that double is passed to the function, where as doing it without <double> would allow for d to be a int or a bool and the code would still compile, silently introducing an error.
(1)That would call the appropriate read<T>(T **data) implementation based on the type T, right?
Yes, assuming the specializations are visible at the point where read<T>(data) is encountered.
(2)If I were to specify a type that is not one of the three above, I'd get a compilation error, since that function is not defined, right?
You haven't provided your declaration of the template read() function, so this can't be answered. Assuming that you have declared it like template <typename T> void read(T**); and have not defined it anywhere then yes, you would get a link-time error when the linker is unable to find an implementation of the requested specialization.
(3)Also, can I make this call:
double **d;
read<double>(d);
to ensure that I called the implementation for double?
You can, though <double> is superfluous and will be inferred.
... silently introducing an error.
If the thing you're passing is a bool** then it would not be an error to use the bool specialization. I don't really see any benefit from explicitly providing the template arguments. If bool** is the wrong type then presumably you would be getting errors somewhere else, anyway.
I guess it depends on what you mean by "silently introducing an error." It's not clear what kind of error you're trying to prevent. I can come up with a contrived example, but contrived examples rarely represent real-world dangers.
Two side notes:
The syntax for your specializations is incorrect. It should be template <> inline void read<bool>(bool **data) { /* ... */ } for example.
There's no need for templates here at all, you can just have three function overloads. Having an undefined template function with explicit specializations is an anti-pattern; overloads are the recommended way to implement the same thing.

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

Using C++ functions in Lua/Binding

so basically I'm trying to find a way to use C++ functions in Lua that are not lua_CFunctions (don't return and int and take a lua_State as a parameter). Basically your regular old C++ function. The catch, though, is I'm trying to find a way to do it without writing it's own dedicated lua_CFunction (so basically imagine I already have a program or a bunch of functions in C++ that I want to use in Lua, and I don't want to have to write a new function for each of them).
So, say I have a very simple C++ function:
static int doubleInt(int a) {
return a*2;
}
(with or without the static, it shouldn't(?) matter).
Say I want to use this function in Lua by calling doubleInt(10) in a lua script. Is there a way to do this without writing a separate
static int callFunc(lua_State *L) {
//do stuff to make the function work in lua
}
for every individual function? So something along the lines of what luaBind does with their def() function (and I know it sucks, but I can't really use a separate dedicated binding library; have to write my own).
I know I have to write a class with templates for this but I don't even have the slightest idea about how to go about getting the function in Lua. I don't think there is a way in C++ to automatically generate a custom function (presumably at compile time) - that would be amazing - so I don't even know where to start.
This is a very open-ended question.
I have been working on a lua binding library recently, so I can explain how I did this, but there are many ways you could do it.
You didn't tag this question C++11. I'm going to assume however that you are using C++11. If not, then it is extremely difficult and I would say not at all practical to roll your own especially if you don't already know enough about boost::mpl to have some idea how to do it. You should definitely just use luabind in that case.
The first thing you need is, you need to create some basic infrastructure that tells you how to convert C++ types to corresponding lua types and back.
IMO the best way to do this is using a type trait, and not one massive overloaded function. So, you will define a primary template:
namespace traits {
template <typename T>
struct push;
template <>
struct push<int> {
static void to_stack(lua_State * L, int x) { lua_pushinteger(L, x); }
};
template <>
struct push<double> {
static void to_stack(lua_State * L, double d) { lua_pushnumber(L, d); }
};
...
} // end namespace traits
Etc. You probably also want to specialize it for std::string and things like that.
Then you can make a generic push function like this:
template <typename T>
void push(lua_State * L, const T & t) {
traits::push<T>::to_stack(L, t);
}
The advantage here is that implicit conversions are not considered when you call push. Either the type you passed exactly matches something you defined the trait for, or it fails. And you can't get ambiguous overload problems between double and int etc., which can be a big pain in the butt.
Then, you have to do the same thing for read, so you have a trait that tells you how to read values of a given type off the stack. Your read technique needs to signal failures somehow, you can decide if that should be using exceptions or a different technique.
Once you have this, you can try to make an adapt template that will take an arbitrary function pointer and try to adapt it into a lua_CFunction that does roughly the same thing.
Basically, you want to use variadic templates so that you can specialize against all the parameters of the function pointer. You pass those types one by one to your read method, and use an index sequence to read from the correct stack positions. You try to read them all, and if you can do it without errors, then you can call the target function, and then you return its results.
If you want to also push generic C++ objects back as the return value, then you can call your push function at the end.
First, to help, you need an "index sequence" facility. If you are in C++14 you can use std::make_integer_sequence, if not then you have to roll your own. Mine looks like this:
namespace detail {
/***
* Utility for manipulating lists of integers
*/
template <std::size_t... Ss>
struct SizeList {
static constexpr std::size_t size = sizeof...(Ss);
};
template <typename L, typename R>
struct Concat;
template <std::size_t... TL, std::size_t... TR>
struct Concat<SizeList<TL...>, SizeList<TR...>> {
typedef SizeList<TL..., TR...> type;
};
/***
* Count_t<n> produces a sizelist containing numbers 0 to n-1.
*/
template <std::size_t n>
struct Count {
typedef
typename Concat<typename Count<n - 1>::type, SizeList<n - 1>>::type type;
};
template <>
struct Count<0> {
typedef SizeList<> type;
};
template <std::size_t n>
using Count_t = typename Count<n>::type;
} // end namespace detail
Here's what your adapt class might look like:
// Primary template
template <typename T, T>
class adapt;
// Specialization for C++ functions: int (lua_State *, ...)
template <typename... Args, int (*target_func)(lua_State * L, Args...)>
class adapt<int (*)(lua_State * L, Args...), target_func> {
template <typename T>
struct impl;
template <std::size_t... indices>
struct impl<detail::SizeList<indices...>> {
static int adapted(lua_State * L) {
try {
return target_func(L, read<Args>(L, 1 + indices)...);
} catch (std::exception & e) {
return luaL_error(L, "Caught an exception: %s", e.what());
}
}
};
public:
static int adapted(lua_State * L) {
using I = detail::Count_t<sizeof...(Args)>;
return impl<I>::adapted(L);
}
};
The real code from my implementation is here. I decided to do it without using exceptions.
This technique also works at compile-time -- since you are passing a function pointer to an arbitrary C++ function as a non-type template parameter, and the adapt template produces a lua_CFunction as a static class member, when you take a pointer to adapt<...>::adapted, it has to all be resolved at compile-time. This means that all the different bits can be inlined by the compiler.
To work around the inability to deduce the type of a non-type template parameter like a function pointer (prior to C++17), I use a macro which looks like this:
#define PRIMER_ADAPT(F) &::primer::adapt<decltype(F), (F)>::adapted
So, I can take a complicated C++ function f, and then use PRIMER_ADAPT(&f) as if it were simply a lua_CFunction.
You should realize though that making all this stuff and testing it takes a really long time. I worked on this library more than a month, and it is refactored out from some code in another project where I had refined it longer. There are also a lot of pitfalls in lua related to "automating" stack operations like this, because it doesn't do any bounds checking for you and you need to call lua_checkstack to be strictly correct.
You should definitely use one of the existing libraries unless you have a really compelling need that prevents it.
If you're not limited to standard Lua lib, you can try LuaJIT. It has ffi support. Calling external function is as simple as:
local ffi = require("ffi")
ffi.cdef[[
int printf(const char *fmt, ...);
]]
ffi.C.printf("Hello %s!", "world")

Template parameters dilemma

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();
...
}