Here, the context of polymorphic is expecting 'Derived' from 'Base&.
Given
class P { };
class Q : public P { };
auto operator + (const P& p, int x) -> DYNAMIC_DECLTYPE(P) {
DYNAMIC_DECLTYPE(P) p2(p);
p2.func(x);
return p2;
}
Is there a way to have DYNAMIC_DECLTYPE working? I want to use this form instead of
template <typename T> T operator + (const T& t, int x)
or have a potentially long list of
if (!strcmp(typeid(p).name(), typeid(derived()).name()) { ... }
because the latter cannot be used to restrict T to P or subclasses thereof (prove me wrong, if possible).
What you are trying to do is in every sense of the word a template pattern: You have an unbounded family of return types with matching function argument types. This should simply be a straight template.
If you want to restrict the permissible types, you should add some typetrait magic. Perhaps like this:
#include <type_traits>
template <typename T>
typename std::enable_if<std::is_base_of<P, T>::value, T>::type
operator+(T const & t, int x)
{
T s(t);
s.func(x);
return s;
}
(If func returns a reference, you can shortcut this to return T(t).func(x);.)
Related
I am trying to built a templated num class. This class needs to have a public attribute, val, with type T, which is the only templated parameter. Furthermore if one provides a value the attribute (val) should be initialized with this value. To do so I made the following code:
#include <iostream>
template<class T>
class Num {
public:
T val;
Num():val(0) { std::cout<<"default constr used"<<std::endl; }
Num(T value):val(value) {std::cout<<"constr (T value) used"<<std::endl; }
~Num() { std::cout<<"destructor used"<<std::endl; }
template<typename U>
Num operator+(const Num<U>& other) {
return val+other.value;
}
};
Furthermore I created the main() function to test the program, which looks like this:
int main() {
std::cout << Num<int>(1) + Num<double>(2.0);
return 0;
}
However the result of the program is now 3. Whereas I expected it to be 3.0 (of type double).
For that you will need to change the return type.
In your code:
// vvv---- Means Num<T>
Num operator+(const Num<U>& other) {
return val + other.val;
}
Indeed, inside a class template, you can type the name of the class without template arguments and it's gonna be somewhat equivalent to writing Num<T>.
Your function is always returning the type of the first operant, no matter the type of the addition itself.
What you want is to deduce that type coming from the addition:
auto operator+(const Num<U>& other) -> Num<decltype(val + other.val)> {
return val + other.val;
}
That way, it's always the right return type according to the C++ operator rules.
operator+ should be symmetric with respect to its arguments. It's better be implemented as a free function rather than a member function to make this symmetry explicit.
For example (using C++14 return type deduction):
template<class T, class U>
auto operator+(const Num<T>& x, const Num<U>& y) {
using R = decltype(std::declval<T>() + std::declval<U>());
return Num<R>{x.val + y.val};
}
std::declval<T>() is there for genericity, if T and/or U are not default constructible. If types are limited to built-in ones, like int and double, it can be replaced with T{} or T():
using R = decltype(T{} + U{});
With class template argument deduction in C++17 it can be simplified further:
template<class T, class U>
auto operator+(const Num<T>& x, const Num<U>& y) {
return Num{x.val + y.val};
}
I'm designing a library for internal use.
A function can be
template<typename It>
void doStuff(It begin, It end)
{
// This is example code. The point is to show that I access the data of the iterator
doStuffInternal(it->a, it->b, it->c);
}
This function is a template because I want to accept all kind of iterators, but I have specific expectations on the type that this iterators produce.
At the moment my code assumes an object is passed with a structure like
struct A
{
int a;
std::string b;
BigObject c;
};
I know the calling code of this function will receive data from an external API, and the data will look something like
struct AlmostA
{
int a_;
std::string _b;
AlmostBigObject cc;
};
Now I can't pass this AlmostA to my function and I need to convert it to A (or something that behaves like A), even if all the information are in AlmostA, just with different names (and slightly different types).
What I'm thinking about doing is to create a function to access the fields
inline int getA(const &A a)
{
return a.a;
}
inline std::string& getB(const &A a)
{
return a.b;
}
and so on for every field I need to access, then rewrite my function to be
template<typename It>
void doStuff(It begin, It end)
{
doStuffInternal(getA(*it), getB(*it), getC(*it));
}
Then the calling code can define
inline int getA(const &AlmostA a)
{
return a.a_;
}
inline std::string& getB(const &AlmostA a)
{
return a._b;
}
and call my function with an iterator of AlmostA without any conversion.
What I hope to achieve with this is that the calling code can define how they provide the information, without being forced to have a structure with those specific fields.
I googled around and couldn't find any example of code doing this.
I'm relatively new to C++, so I'd like if this would work, what are the pitfalls of this approach, why is it not popular or not used (I know something kind of similar is done with std::swap, but that's a particular function) what are alternative solutions to present data with different interface in a unified way in the C++ world?
In what namespace does the getter function need to be implemented in order for the compiler to find them?
Your doStuffInternal(getA(*it), getB(*it), getC(*it)) seems solid to me - I would use a struct template with an explicit specialization for every type that you need to support.
template <typename T>
struct adapter;
template <>
struct adapter<A>
{
template <typename T>
decltype(auto) a(T&& x) { return forward_like<T>(x.a); }
template <typename T>
decltype(auto) b(T&& x) { return forward_like<T>(x.b); }
// ...
};
template <>
struct adapter<AlmostA>
{
template <typename T>
decltype(auto) a(T&& x) { return forward_like<T>(x.a_); }
template <typename T>
decltype(auto) b(T&& x) { return forward_like<T>(x._b); }
// ...
};
Using decltype(auto) as the return type and forward_like allows you to preserve the value category of x's members:
static_assert(std::is_same<decltype(adapter<A>::a(A{})), int&&>{});
A lvalue{};
static_assert(std::is_same<decltype(adapter<A>::a(lvalue)), int&>{});
const A const_lvalue{};
static_assert(std::is_same<decltype(adapter<A>::a(const_lvalue)), const int&>{});
wandbox example (of the value category propagation)
The final code will look something like this:
template<typename It>
void doStuff(It begin, It end)
{
adapter<std::decay_t<decltype(*it)>> adp;
doStuffInternal(adp.a(*it), adp.b(*it), adp.c(*it));
}
In C++11, you need to explicitly specify the return type using a trailing return type. Example:
template <typename T>
auto a(T&& x) -> decltype(forward_like<T>(x.a_))
{
return forward_like<T>(x.a_);
}
In Haskell, typeclasses allow for you to elegantly overload functions based on return type. It is trivial to replicate this in C++ for cases where both the arguments and the return type are overloaded, using templates (example A):
template <typename In, typename Out> Out f(In value);
template <typename T> int f<T, int>(T value) {
...
}
Which corresponds to Haskell's:
class F a b where
f :: a -> b
You can even overload just the return type on most functions (example B):
template <typename Out> Out f(SomeClass const &value);
template <> inline int f(SomeClass const &value) {
return value.asInt();
}
template <> inline float f(SomClass const &value) {
return value.asFloat();
}
Which corresponds to something like:
class F a where
f :: SomeData -> a
But what I would like to be able to do is modify this last example to overload on higher-order types, namely templated structs in C++. That is, I'd like to be able to write a specialization akin to the following Haskell:
data Foo a = Foo a
instance F (Foo a) where
f someData = Foo $ ...
How would one go about writing a template with this functionality (is it even possible)?
For reference, I'm intending to use this to write template functions for Lua/C++ bridge. The idea is to bridge between Lua and C++ functions by having an overloaded function interpretValue that automatically pushes or converts from the Lua stack. For simple types that have a direct built-in Lua representation, this is easy enough using code such as example B.
For more complicated types, I'm also writing a template <typename T> struct Data to handle memory management for objects (bridging between Lua's GC and a C++ side refcount), and I was hoping to be able to overload interpretValue so that it can automatically wrap a userdata pointer into a Data<T>. I tried using the following, but clang gave a "function call is ambiguous" error:
template <typename U> inline U &interpretValue(lua_State *state, int index) {
return Data<U>::storedValueFromLuaStack(state, index);
}
template <typename U> inline Data<U> interpretValue(lua_State *state, int index) {
return Data<U>::fromLuaStack(state, index);
}
Thanks!
Well, you can write one function:
template <class U>
interpretValueReturnType<U> interpretValue(lua_State *state, int index)
{
return interpretValueReturnType<U>(state, index);
}
Then, you need to write this return type with casting operators, so, you get what you want:
template <class U>
class interpretValueReturnType
{
public:
interpretValueReturnType(lua_State *state, int index) : state(state), index(index) {}
operator U& () &&
{
return Data<U>::storedValueFromLuaStack(state, index);
}
operator Data<U> () &&
{
return Data<U>::fromLuaStack(state, index);
}
private:
lua_State *state;
int index;
};
See ideone:
int main() {
lua_State *state;
int& a = interpretValue<int>(state, 1);
Data<int> b = interpretValue<int>(state, 1);
}
This funny && at the end of operators declarations are for making a little hard to store result of this function and use it later - like here:
auto c = interpretValue<float>(state, 1);
float& d = c; // not compile
One'd need to use std::move because && means that function can be used only for rvalue references:
auto c = interpretValue<float>(state, 1);
float& d = std::move(c);
Say I currently have a template function like this:
template <class T, class K>
void* get_subobject(K key)
{
T& obj = function_returning_T_ref<T>();
// do various other things...
return &obj[key];
}
And I would like to make the subscript operation configurable so that the user could apply their own code to map obj and key to the return value. Something like this:
template <class T, class K, class Op = subscript<T, K>>
void* get_subobject(K key)
{
T& obj = function_returning_T_ref<T>();
// do various other things...
return &Op{}(obj, key);
}
My question is, for the default template parameter subscript<T,K> above is there a standard template (along the lines of std::less<T>) that I can use here so that Op defaults to calling operator[]? I can't see anything appropriate in <functional>.
If there is no standard template for this, am I best to create my own or is there some way I can use std::bind() or similar to the same effect without additional overhead?
I don't know of any built-in template, but it's not too hard to create your own (that, once inlined, will have no overhead):
template<typename T, typename K>
struct subscript
{
inline auto operator()(T const& obj, K const& key) const -> decltype(obj[key])
{
return obj[key];
}
inline auto operator()(T& obj, K const& key) const -> decltype(obj[key])
{
return obj[key];
}
};
You could even have one that worked on implicit types (I like this one best):
struct subscript
{
template<typename T, typename K>
inline auto operator()(T&& obj, K&& key) const
-> decltype(std::forward<T>(obj)[std::forward<K>(key)])
{
return std::forward<T>(obj)[std::forward<K>(key)];
}
};
The user, of course, can pass in any conforming type of their own, including a std::function object or plain function pointers.
Please, consider the code below:
template<typename T>
bool function1(T some_var) { return true; }
template <typename T>
bool (*function2())(T) {
return function1<T>;
}
void function3( bool(*input_function)(char) ) {}
If I call
function3(function2<char>());
it is ok. But if I call
function3(function2());
compiler gives the error that it is not able to deduction the argument for template.
Could you, please, advise (give an idea) how to rewrite function1 and/or function2 (may be, fundamentally to rewrite using classes) to make it ok?
* Added *
I am trying to do something simple like lambda expressions in Boost.LambdaLib (may be, I am on a wrong way):
sort(some_vector.begin(), some_vector.end(), _1 < _2)
I did this:
template<typename T>
bool my_func_greater (const T& a, const T& b) {
return a > b;
}
template<typename T>
bool my_func_lesser (const T& a, const T& b) {
return b > a;
}
class my_comparing {
public:
int value;
my_comparing(int value) : value(value) {}
template <typename T>
bool (*operator<(const my_comparing& another) const)(const T&, const T&) {
if (this->value == 1 && another.value == 2) {
return my_func_greater<T>;
} else {
return my_func_greater<T>;
}
}
};
const my_comparing& m_1 = my_comparing(1);
const my_comparing& m_2 = my_comparing(2);
It works:
sort(a, a + 5, m_1.operator< <int>(m_2));
But I want that it doesn't require template argument as in LambdaLib.
Deduction from return type is not possible. So function2 can't be deduced from what return type you expect.
It is however possible to deduce cast operator. So you can replace function2 with a helper structure like: Unfortunately there is no standard syntax for declaring cast operator to function pointer without typedef and type deduction won't work through typedef. Following definition works in some compilers (works in G++ 4.5, does not work in VC++ 9):
struct function2 {
template <typename T>
(*operator bool())(T) {
return function1<T>;
}
};
(see also C++ Conversion operator for converting to function pointer).
The call should than still look the same.
Note: C++11 introduces alternative typedef syntax which can be templated. It would be like:
struct function2 {
template <typename T>
using ftype = bool(*)(T);
template <typename T>
operator ftype<T>() {
return function1<T>;
}
};
but I have neither G++ 4.7 nor VC++ 10 at hand, so I can't test whether it actually works.
Ad Added:
The trick in Boost.Lambda is that it does not return functions, but functors. And functors can be class templates. So you'd have:
template<typename T>
bool function1(T some_var) { return true; }
class function2 {
template <typename T>
bool operator()(T t) {
function1<T>;
}
};
template <typename F>
void function3( F input_function ) { ... input_function(something) ... }
Now you can write:
function3(function2);
and it's going to resolve the template inside function3. All STL takes functors as templates, so that's going to work with all STL.
However if don't want to have function3 as a template, there is still a way. Unlike function pointer, the std::function (C++11 only, use boost::function for older compilers) template can be constructed from any functor (which includes plain function pointers). So given the above, you can write:
void function3(std::function<bool ()(char)> input_function) { ... input_function(something) ... }
and now you can still call:
function3(function2());
The point is that std::function has a template constructor that internally generates a template wrapper and stores a pointer to it's method, which is than callable without further templates.
Compiler don't use context of expression to deduce its template parameters. For compiler, function3(function2()); looks as
auto tmp = function2();
function3(tmp);
And it don't know what function2 template parameter is.
After your edit, I think what you want to do can be done simpler. See the following type:
struct Cmp {
bool const reverse;
Cmp(bool reverse) : reverse(reverse) {}
template <typename T> bool operator()(T a, T b) {
return reverse != (a < b);
}
};
Now, in your operator< you return an untyped Cmp instance depending on the order of your arguments, i.e. m_2 < m_1 would return Cmp(true) and m_1 < m_2 would return Cmp(false).
Since there is a templated operator() in place, the compiler will deduce the right function inside sort, not at your call to sort.
I am not sure if this help you and I am not an expert on this. I have been watching this post since yesterday and I want to participate in this.
The template cannot deduce it's type because the compiler does not know what type you are expecting to return. Following is a simple example which is similar to your function2().
template<typename T>
T foo() {
T t;
return t;
};
call this function
foo(); // no type specified. T cannot be deduced.
Is it possible to move the template declaration to the class level as follows:
template<typename T>
bool my_func_greater (const T& a, const T& b) {
return a > b;
}
template<typename T>
bool my_func_lesser (const T& a, const T& b) {
return b > a;
}
template <typename T>
class my_comparing {
public:
int value;
my_comparing(int value) : value(value) {}
bool (*operator<(const my_comparing& another) const)(const T&, const T&) {
if (this->value == 1 && another.value == 2) {
return my_func_greater<T>;
} else {
return my_func_greater<T>;
}
}
};
and declare m_1 and m_2 as below:
const my_comparing<int>& m_1 = my_comparing<int>(1);
const my_comparing<int>& m_2 = my_comparing<int>(2);
Now you can compare as follows:
if( m_1 < m_2 )
cout << "m_1 is less than m_2" << endl;
else
cout << "m_1 is greater than m_2" << endl;
I know this is simple and everyone knows this. As nobody posted this, I want to give a try.