In my TClass<T>::foo() function, I'd like to invoke a T instance if and only if T is a function type.
#include <iostream>
#include <functional>
template<class T>
struct TClass
{
TClass(T value) : value(value) {}
T value;
void foo()
{
// if(value is std::function)
// call function;
}
};
int main()
{
TClass<int> t1{0};
t1.foo();
TClass<std::function<void()>> t2{[](){ std::cout << "Hello, World!\n"; }};
t2.foo();
}
How can I do that?
In C++11, the easiest way to do this is to re-deduce the value through a helper function:
template <typename U>
auto foo_helper(U const& f, int) -> decltype(f()) {
return f();
}
template <typename U>
void foo_helper(U const&, long) {}
void foo() {
foo_helper(value, 0);
}
The conversion from 0 to int is better than its conversion to long, so if the first overload is viable - it will be preferred. If the first overload isn't viable, then we call the second one.
If you really care only about std::function, then we can just have simpler overloads:
void foo_helper(std::function<void()> const& f) {
f();
}
template <typename T>
void foo_helper(T const&) { }
void foo() {
foo_helper(value);
}
In C++17 you can do:
void foo() {
if constexpr (std::is_invocable_v<T>) {
value();
}
}
If you only wants to allow std::function, you'll need your own trait, e.g.:
template <class T>
struct is_stdfunction: std::false_type {};
template <class T>
struct is_stdfunction<std::function<T>: std::true_type {};
template <class T>
constexpr bool is_stdfunction_v = is_stdfunction<T>::value;
// Then in foo():
void foo() {
if constexpr (is_stdfunction_v<std::decay_t<T>>) {
value();
}
}
Why not partial specialization ?
Consider:
#include <iostream>
#include <functional>
template<class T>
struct TClass {
TClass(T value) : value(value) {}
T value;
void foo() {
std::cout << "T - other" << std::endl;
}
};
template<class T>
struct TClass<std::function<T>> {
TClass(std::function<T> value) : value(value) {}
std::function<T> value;
void foo() {
std::cout << "std::function" << std::endl;
}
};
Related
I want to do multiple inheritance via template arguments and pass reference to this in each base class, so I can call top level object's method from each base class's method. I can do it with manual inheritance, but I want to be able to do this via templates arguments.
Godbolt link
Godbolt link with manual inheritance
#include <cstdio>
template <typename T>
struct Foo {
Foo(T &t)
: t_(t) {
}
void foo() {
t_.call("foo");
}
T &t_;
};
template <typename T>
struct Bar {
Bar(T &t)
: t_(t) {
}
void bar() {
t_.call("bar");
}
T &t_;
};
template <template<typename> typename... Methods>
struct Impl : public Methods<Impl>... {
Impl()
: Methods<Impl>(*this)... {
}
void call(const char *m) {
printf(m);
}
};
int main() {
auto t = Impl<Foo, Bar>();
t.foo();
t.bar();
}
I tried this approach, but it gives
type/value mismatch at argument 1 in template parameter list for 'template<class> class ... Methods'
Thanks to #Nicol Bolas, he advised to use static_cast and CRTP for this
#include <cstdio>
template <typename T>
struct Foo {
void foo() {
static_cast<T*>(this)->call("foo");
}
};
template <typename T>
struct Bar {
void bar() {
static_cast<T*>(this)->call("bar");
}
};
template <template<typename> typename... Methods>
struct Impl : public Methods<Impl<Methods...>>... {
Impl() {
}
void call(const char *m) {
printf(m);
}
};
int main() {
auto t = Impl<Foo, Bar>();
t.foo();
t.bar();
}
In C++20, we can now use concepts instead of SFINAE to figure out whether a function exists in a template typename:
template<typename T> concept fooable = requires (T a) {
a.foo();
};
class Foo {
public:
// If commented out, will fail compilation.
void foo() {}
void bar() {}
};
template <typename T> requires fooable<T>
void foo_it(T t) {
t.bar();
}
int main()
{
foo_it(Foo());
}
How do we do this with functions that have non-empty arguments?
You might have extra parameters in requires:
template<typename T> concept fooable = requires (T a, int i) {
a.foo(i);
};
Demo
The best option seems to be declval:
template<typename T> concept fooable = requires (T a) {
a.foo(std::declval<int>());
};
class Foo {
public:
void foo(int x) {}
void bar() {}
};
template <typename T> requires fooable<T>
void foo_it(T t) {
t.bar();
}
int main()
{
foo_it(Foo());
}
Does anybody know how to make a C++ concept T such that the function g is only defined for arguments t with type T if there exist an overload of f in B that accepts an argument t?
struct A1 {};
struct A2 {};
struct B {
void f(A1 a1) {}
};
void g(T t) {
B b;
b.f(t);
}
As an example, I want to define a to_string for everything that std::stringstream accepts, and define something like
std::string to_string(T t) {
std::stringstream ret;
ret << t;
return ret.str();
}
All examples on concepts deal with the easier case of requiring the existance of a function on a type, while in this case we want to check existance of a function on another type.
If you want to check if the type is streamable or not, you can have something like:
#include <iostream>
#include <concepts>
#include <sstream>
template <typename T>
concept Streamable = requires (T x, std::ostream &os) { os << x; };
struct Foo {};
struct Bar {};
std::ostream& operator<<(std::ostream& os, Foo const& obj) {
// write obj to stream
return os;
}
template <Streamable T>
std::string to_string(T t) {
std::stringstream ret;
ret << t;
return ret.str();
}
int main() {
Foo f;
Bar b;
to_string(f);
to_string(b); // error
return 0;
}
Demo
You can use two different type placeholders in a single concept, to require both the existence of a member function for an instance of one of the type placeholders, as well as the argument to said member function to match the type of another placeholder. E.g.:
#include <iostream>
template<typename T, typename U>
concept HasMemFnConstFoo = requires(const T t, const U u) {
t.foo(u);
};
template<typename U>
struct Bar {
template <typename T>
static void bar(const T& t)
{
if constexpr (HasMemFnConstFoo<T, U>) { t.foo(U{}); }
else { std::cout << "foo() not defined\n"; }
}
};
struct A1 {};
struct A2 {};
struct B1 {
void foo(const A1&) const { std::cout << "B1::foo()\n"; }
};
struct B2 {
void foo(const A1&) { std::cout << "B2::foo()\n"; }
};
struct B3 {
void foo(A1&) const { std::cout << "B3::foo()\n"; }
};
int main() {
Bar<A1>::bar(B1{}); // B1::foo()
Bar<A2>::bar(B1{}); // foo() not defined
Bar<A1>::bar(B2{}); // foo() not defined [note: method constness]
Bar<A2>::bar(B2{}); // foo() not defined
Bar<A1>::bar(B3{}); // foo() not defined [note: argument constness]
Bar<A2>::bar(B3{}); // foo() not defined
}
Consider the following, minimal example:
struct S {
using func_t = void(*)(void *);
template<typename T>
static void proto(void *ptr) {
static_cast<T*>(ptr)->f();
}
func_t func;
void *ptr;
};
struct T {
void f() {}
};
void g(S &s) {
s.func(s.ptr);
}
int main() {
T t;
S s;
s.func = &S::proto<T>;
s.ptr = &t;
g(s);
}
The pretty obvious idea is to erase the type of a bunch of objects (like T, that is not the only available type) to create an array of instances of S, then iterate over that array and invoke a predetermined member function.
So far so good, it's easy to implement and it works.
Now I would like to provide an external function to be invoked on the erased object, something that would be like this:
template<typename T, typename F>
static void proto(void *ptr, F &&f) {
auto *t = static_cast<T*>(ptr);
std::forward<F>(f)(*t);
t->f();
}
Or this:
template<typename T>
static void proto(void *ptr, void(*f)(T &)) {
auto *t = static_cast<T*>(ptr);
f(*t);
t->f();
}
To be invoked as:
s.func(s.ptr, [](auto obj){ /* ... */ });
A kind of template method pattern where the extra functionalities are provided by the caller instead of a derived class.
Unfortunately I cannot do that for I cannot reduce the specializations to something homogeneous to be assigned to a function pointer.
The only alternative I can see is to define a custom class like the following one:
struct C {
template<typename T>
void f(T &t) { /* ... */ }
// ...
};
Where f dispatches somehow the call internally to the right member function, then use it as:
struct S {
using func_t = void(*)(void *, C &);
template<typename T>
static void proto(void *ptr, C &c) {
auto t = static_cast<T*>(ptr);
c.f(*t);
t->f();
}
func_t func;
void *ptr;
};
That is not far from what I would do by using a lambda, but it's more verbose and requires me to explicitly declare the class C.
Is there any other valid alternative to achieve the same or is this the only viable solution?
Assuming you can enumerate the types you wish to support you can do this:
#include <iostream>
#include <string>
#include <vector>
template <class... Ts>
struct PseudoFunction {
private:
template <class T>
static void (*function)(T &);
template <class T>
static void call_func(void *object) {
return function<T>(*static_cast<T *>(object));
}
template <class Fun>
static void assign(Fun) {}
template <class Fun, class Head, class... Tail>
static void assign(Fun fun) {
function<Head> = fun;
assign<Fun, Tail...>(fun);
}
public:
template <class T>
PseudoFunction(T *t)
: object(t)
, func(call_func<T>) {}
template <class F>
static void set_function(F f) {
assign<F, Ts...>(f);
}
void operator()() {
func(object);
}
private:
void *object;
void (*func)(void *);
};
template <class... Ts>
template <class T>
void (*PseudoFunction<Ts...>::function)(T &) = nullptr;
//example types that are not related and not copy constructible
//but have the same member function name and signature
struct T1 {
T1() = default;
T1(const T1 &) = delete;
void func(double d) {
std::cout << "T1: " + std::to_string(d) + '\n';
}
};
struct T2 {
T2() = default;
T2(const T2 &) = delete;
void func(double d) {
std::cout << "T2: " + std::to_string(d) + '\n';
}
};
int main() {
T1 t1;
T2 t2;
using PF = PseudoFunction<T1, T2>;
std::vector<PF> funcs;
funcs.push_back(&t1);
funcs.push_back(&t2);
PF::set_function([](auto &object) { object.func(3.14); });
for (auto &f : funcs) {
f();
}
}
(demo)
It has decent call syntax (just that you have to specify the function before calling the objects) and some overhead of setting potentially unused function pointers.
One could probably make a wrapper that does the set_function and iterating over the PFs in one go.
First, I've read over many other questions and couldn't find the solution. So before marking it a duplicate, please make sure duplicate answers the question.
I'm trying to specialize F::operator() for a class C2; however, C2 has a template parameter and I want F::operator() to behave the same for all C2's.
Compiler error:
error: invalid use of incomplete type ‘struct F<C2<T> >’
void F<C2<T>>::operator()()
Also, instead of Handle& h, I tried Handle* h and received the same error.
#include<iostream>
struct C1
{
void foo()
{
std::cout << "C1 called" << std::endl;
}
};
template<typename T>
struct C2
{
void bar();
};
template<>
void C2<int>::bar()
{
std::cout << "C2<int> called" << std::endl;
}
template<typename Handle>
struct F
{
F(Handle& h_) : h(h_) {}
void operator()();
Handle& h;
};
template<>
void F<C1>::operator()()
{
h.foo();
}
template<typename T>
void F<C2<T>>::operator()()
{
h.bar();
}
int main()
{
C1 c1;
F<C1> f_c1 (c1);
f_c1();
C2<int> c2;
F<C2<int>> f_c2 (c2);
f_c2();
}
There's no such thing like a partial specialization of a member function. You'd need to first partial-specialize the entire class:
template <typename T>
struct F<C2<T>>
{
void operator()();
};
template <typename T>
void F<C2<T>>::operator()() {}
Since this is a heavy-weight solution, alternatively, you can exploit tag-dispatching:
template <typename T> struct tag {};
template <typename Handle>
struct F
{
F(Handle& h_) : h(h_) {}
void operator()()
{
call(tag<Handle>{});
}
private:
void call(tag<C1>)
{
h.foo();
}
template <typename T>
void call(tag<C2<T>>)
{
h.bar();
}
Handle& h;
};
DEMO