template with duck typing in C++ - c++

Is there a way to require a templates type to have properties?
For example:
template <typename T, typename U>
void foo()
{
U a,b;
bool truthiness = T()(a,b);
if (truthiness)
// do something
}
So, how would I require that T have the operator()(U a, U b) defined, that returns a specific type? Is this possible? (I know it is in d, but I'm not sure about c++).
ps. if duck typing is wrong here, let me know, I believe it is correct, but I'm not sure.

Your syntax is wrong, considering your intent. Since T is a type, T(1, 2) would construct a temporary object of type T using a two-parameter constructor. If you wanted to call Ts operator () you'd have to вo something like
T()(1, 2);
assuming a call through a temporary works for your purposes.
If T had no such operator (), the code would simply fail to compile. I'd actually say that one big benefit of template code is that it "works" as long as the syntax is valid (i.e. the very duck-typing you are talking about), i.e. there's no need to further restrict it by requiring the operator () be present.
Of course, in my example it might actually make sense, since for T = void (*)(int, int) the code would be syntactically valid, but would result in a function call through a null pointer. But again, that's specific to my version of the code, and I don't know what specific object of type T you want to apply your operator () to.
Having said that, it is worth nothing that Boost library has quite a few features that allows one to check such properties and use them for branching in template meta-programming and/or in static assertions.

By simple expressing the template then you require for T to have operator()(int, int). It will not compile if it doesn't.
However if you are creating an API and want to inform the user of the API that they have passed in an incompatible type then you need to create a type trait which detects the operator and you can specialise the function to discriminate on that fact and create a static_assert to indicate the fact.

If you have access to decltype, you can roll your own check relatively easily.
template <class T, class U> class check_same_type_t;
template <class T> class check_same_type_t<T, T> { };
template <class T, class U>
void foo()
{
U a,b;
check_same_type_t<bool, decltype(T()(a, b))> check;
bool truthiness = T()(a,b);
if (truthiness) ;
// do something
}
Which enables the following:
struct A {
bool operator()(int, int) { return true; }
};
struct B {
int operator()(int, int) { return 1; }
};
int
main()
{
foo<A, int>(); // will compile
foo<B, int>(); // won't compile
}
Just make sure that this what you really want. Forcing a generic algorithm to use a specific type may potentially come back to bite you. If a type is implicitly convertible to bool, why is it unsatisfactory to use in your condition?

Related

C++ detect if a type can be called with a template type

I'm working on a program where some data is statically allocated and some is dynamically allocated. Now I want to have another type that can be called with any template of the type as its argument.
#include <array>
#include <vector>
template <int size> class Foo {
std::array<int, size> data;
public:
int& operator[](std::size_t idx) {return data[idx];}
};
template <> class Foo<-1> {
std::vector<int> data;
public:
int& operator[](std::size_t idx) {return data[idx];}
};
// option 1- polymorphism
struct FooCaller {
virtual void operator()(Foo data) = 0; // how would I make this work with both forms of Foo?
};
// option 2- generic programming
template <class T> concept CanCallFoo = requires (const T& t) {
t(std::declval<Foo&>()); // how do I ensure that this can call any overload of Foo?
};
Both methods would be fine, but I'm not sure how to go about this. Because the full code is more complex, I'd rather not have both Foos inherit from a base.
A callable F could write a restriction that it can be called by Foo<x> such that an arbitrary function of x must be true to be valid.
In order for your "can be called with any Foo" test to work, you would have to invert an arbitrary function at compile time.
There is no practical way to do this short of examinjng all 2^32 possible values of x. No, really. The problem you have is that the type F is possibly too powerful for you to determine its properties. This is related to Halt and Rice's theorem and the fact that template metaprogramming and C++ overload resolution is Turing complete (only related, because 2^32 is finite).
In the other case, you could type erase. Write a type RefAnyFoo/AnyFooValue that can be constructed from any Foo type and "type erases" the operations you want, like how std::function<void(int)> type erases. It could either duck type the Foo or actually restrict to instsnces of types made from the template.
Then your interface is one that takes a AnyFooValue/RefAnyFoo (depending if you are talking about copies or references).
Now, flipping this over, you can write a concept that accepts F that take RefFooAny. This isn't quite what you asked for, but plausibly you have an X/Y problem; you had a real problem, came up with incomplete solutions, then asked about how to get your solutions working, instead of the original problem.
Similarly, it is possible you only care about certain ducktype properties of Foo<?> and not the specific type. Then a concept that checks those ducktypes could be used by your callable; this again deosn't solve your problem, as much as it flips it upside down, because you cannot verify a callable accepts an entire concept from outside the callable.

Can concepts restrict the type member variables?

I'm using C++20 & I'm wondering if Concepts is at all possible to solve a situation like this.
Let's say I have a function:
template <typename F>
void doSomething(F f) {
f();
}
doSomething accepts a callable objects (technically lambdas but shouldn't matter I think) & I want to ensure that no member variables of F have a type T. For example, I want:
BadType t;
int x = ...;
double y = ...;
doSomething([t = kj::mv(t), x, y] { ... }); // I want a compile error
doSomething([x, y] { ... }); // No error.
Similarly, I want to validate the arguments of the callable in a similar way:
doSomething([x, y](BadType t) { ... }); // I want a compile error
doSomething([x, y](std::vector<int> c) { ... }); // No compile error
I don't know if this complicates things, but technically BadType itself is a templated type (I want to disable all instances regardless of the template value).
An acceptable answer could be one that provides an example, but I'm also happy with good tutorials that someone feels I should be could be able to cobble together to accomplish. I'm very experienced with C++ & template meta-programming, but concepts feel like a totally alien thing at the moment. Of course, if this isn't possible, then happy to accept such an answer too.
This feels like something that the Reflection TS would be perfect for, but alas clang doesn't have this in an accessible way even in v13 (& I think similarly the GCC work is in a non-mainline branch still). I've explored various static reflection libraries for C++17, but they all suffer from needing to modify the type, which isn't possible here since I'm introspecting a lambda (and BadType is a type defined in a 3p library although that shouldn't matter).
I suspect the answer must be no since each lambda I pass in will have an arbitrary set of names for the variables that get captured & the only examples I've seen of concepts trying to enforce the type of a member variable require a single known variable name, but maybe this is an interesting challenge for someone who's a Concepts master.
You can easily check if a simple struct/aggregate T contains any field with type TType using boost::pfr:
#include <boost/pfr.hpp>
template <typename TType, typename T>
[[nodiscard]] constexpr bool has_any_data_member_of_type() noexcept
{
return []<std::size_t... Is>(std::index_sequence<Is...>)
{
return (std::is_same_v<boost::pfr::tuple_element_t<Is, T>, TType> || ...);
}(std::make_index_sequence<boost::pfr::tuple_size_v<T>>{});
}
struct a { int i; float f; char c; };
struct b { int i; char c; };
static_assert( has_any_data_member_of_type<float, a>());
static_assert(!has_any_data_member_of_type<float, b>());
live example on godbolt.org
You can then easily define a concept for that:
template <typename T, typename TType>
concept having_any_data_member_of_type = has_any_data_member_of_type<TType, T>();
Unfortunately, since lambda expressions are not aggregates, you won't be able to use them with has_any_data_member_of_type. However, custom callable objects work:
struct my_callable
{
float f;
float operator()() { return f; }
};
void f0(having_any_data_member_of_type<float> auto f)
{
(void) f();
}
int main()
{
f0(my_callable{}); // OK
}
If you are happy with checking only a direct nesting of an object inside a simple struct/aggregates see Vittorio's answer.
If your goal is to prohibit capturing an object of some type inside callable objects (for example, prohibiting capturing a reference in the asynchronous callback or prohibiting capturing some object that should not be accessed from callback) then it is impossible in the general case even with reflection TS.
Simple counter example:
BadType t;
doSomething([t = std::any(kj::mv(t))]{...}); // Even reflection TS could not do anything with this.
Another one:
struct Fun {
std::any v;
void operator()() {
....
}
}
Fun f = ...
doSomething(std::move(f)); // Event more powerful reflection than reflection TS (reflection with statements reflection) could not do anything with this.
Even if nesting in multiple layers of objects could be taken into account any kind of type-erasure simply could not.

C++ Method argument can be either primitive or object

Let's say I have a C++ class Foo. It has a templatized method setValue() that needs to accept any of the following as its argument:
Any primitive type
An object of type Bar
An object of a subclass of Bar
I want to write something like this.
template <class T>
void setValue(T& value) {
if (std::is_fundamental<T>::value)
setPrimitiveValue(value)
else {
Bar* bar = dynamic_cast<Bar*>(&value);
if (bar != NULL)
setBarValue(*bar);
}
}
But this doesn't compile. When I call the method with an int, the compiler complains that dynamic_cast can't be used on an int*. Even though that code branch doesn't get executed for primitives, the compiler still needs to compile it.
How can I make this work? Note this is a method in a class, so template specializations aren't allowed.
Since C++17 you can easily address this problem with if constexpr.
As you can expect, it can exclude an entire branch from the compilation (rather than the execution, as a normal if).
Note: the code is still subjected to syntax rules. Details are out of the scope of this answer.
template <class T>
void setValue(T& value) {
if constexpr (std::is_fundamental<T>::value)
setPrimitiveValue(value)
else {
Bar* bar = dynamic_cast<Bar*>(&value);
if (bar != NULL)
setBarValue(*bar);
}
}
The answer from Biagio Festa looks perfect as long as you can use C++17. I can't since I still need to support older compilers, but that answer led me to Constexpr if alternative which gives several alternatives. Here's the solution I ended up with which works even on C++11.
template <class T>
typename std::enable_if<std::is_fundamental<T>::value, void>::type setValue(T& value) {
setPrimitiveValue(value);
}
void setValue(Bar& value) {
setBarValue(value);
}

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.

Templated operator[]... possible? Useful?

Could you have:
template <class T>
const T &operator[] (unsigned int x)
My thinking was if you have a map<string,string> it would be nice to have a wrapper class which lets you do:
obj["IntVal"]="12";
obj["StringVal"]="Test";
int i = obj["IntVal"];
How close to this can we actually get in C++? Is it worth the pain?
You can also do
class Class {
struct Proxy {
template<typename T> T as() { ... }
template<typename T> operator T() { return as<T>(); }
private:
Proxy(...) { ... }
Proxy(Proxy const&); // noncopyable
Proxy &operator=(Proxy const&);
friend class Class;
};
public:
Proxy operator[](std::string const& s) { ... }
};
Class a;
int i = a["foo"];
int i = a["foo"].as<int>();
T will be deduced to whatever the to be initialized object is. And you are not allowed to copy the proxy. That said, i prefer an explicit as<T> function like another one proposed too.
You can't - in:
int i = obj["IntVal"];
the actual type of T can't be inferred from the context since the return type isn't part of the function signature.
Moreover, storing integer values as strings is not considered as best practices, due to memory and performance considerations ;-)
Not worth it.
Templating the return type means you'd have to explicitly specify the template parameter when you call it. Something like this, maybe I have the syntax wrong:
int i = obj.operator[]<int>("IntVal");
C++ does not deduce template parameters from what you assign the result of the call to, only from the parameters you call the function with.
So you might as well just define a normal function:
int i = obj.get<int>("IntVal");
Or in this case, either do this or implement get using this:
int i = boost:lexical_cast<int>(obj["IntVal"]);
As Amit says, you could define operator[] to return a type which can be converted either to int or to other types. Then your example code can be made to compile without the explicit lexical_cast.
Have you looked at boost variant? Is this what you're looking for?
Well, what you wrote in your sample code doesn't match the question. Right now, you only have the return type templated.
But if you wanted to do something like:
template <class T>
const T &operator[const T& x]
that's valid, though maybe not terribly useful.
A map already provides an overloaded operator[] that does most of what you want. The thing you seem to want that's missing is implicit conversion from a string that happens to contain digits to an integer. One of the fundamental characteristics of C++ is static typing, which says that shouldn't be allowed -- so it's not. It'll be happy to do that conversion if you want, but you'll have to ask for it:
int i = lexical_cast<int>(obj["IntVal"]);
Alternatively, you could create a string-like class that supported implicit conversion to int. Personally, I'd advise against that. I don't object to implicit conversions nearly as strongly as many people do, but that still strikes me as a pretty lousy idea, at least for most general use.