6

I am trying to achieve the following:

template<template<typename> bool Function_, typename ... Types_>
constexpr auto find(Tuple<Types_ ... >) noexcept
{
    // ... 
}

where a possible function could be:

template<typename T>
inline constexpr bool is_pointer_v = is_pointer<T>::value;

so then the usage of find would be:

Tuple<int, char, void *> t;
find<is_pointer_v>(t);

don't worry about the implementation of find, I am just asking about how to do "template < typename > bool Function_" as the bool part is invalid in c++ currently.

any help is appreciated!

EDIT:

here is an example of why I can't pass the "is_pointer" to the function:

template<typename T_>
constexpr auto add_pointer(Type<T_>) noexcept
{ return type_c<T_ *>; }

template<typename F_, typename T_>
constexpr auto apply(F_ f, Type<T_> t) noexcept
{
    return f(t);
}

int main(void)
{
    Type<int> t_i;
    apply(add_pointer, t_i);
}

this produces the compiler error:

error: no matching function for call to ‘apply(< unresolved overloaded function type >, sigma::meta::Type&)’ apply(add_pointer, t_i);

AndyG
  • 39,700
  • 8
  • 109
  • 143
  • 1
    You could take `is_pointer` as a normal template template-parameter, and access its `value` member in the body. – Igor Tandetnik Jul 12 '17 at 04:16
  • unfortunately i'm using a more boost::hana styled approach where all the "is_pointer" structs are actually functions – Fletcher Blight Jul 12 '17 at 04:25
  • 1
    If they are actually functions, you can take one as a normal type parameter. I don't suppose you could show a motivating example? – Igor Tandetnik Jul 12 '17 at 04:30
  • This looks like C++14, not C++11. – AndyG Jul 12 '17 at 16:52
  • Also sounds like an XY problem. It appears that what you're actually trying to do is filter a tuple by types, or maybe find the first element in a tuple whose type satisfies some predicate. Please clarify; I think it's important to know the true purpose of your `find` function. – AndyG Jul 12 '17 at 17:51
  • @AndyG it's actually C++17, if constexpr is essential for the meta library I'm making. I was mainly asking how to pass a templated constexpr variable to a function but I've learnt that's not possible – Fletcher Blight Jul 13 '17 at 00:20

2 Answers2

2

any help is appreciated!

You can simply wrap your functions within functors.
As a minimal, working example:

template<typename>
struct Type {};

template<typename>
struct type_c {};

template<typename T_>
struct add_pointer {
    static constexpr auto invoke(Type<T_>) noexcept
    { return type_c<T_ *>{}; }
};

template<template<typename> class F_, typename T_>
constexpr auto apply(Type<T_> t) noexcept {
    return F_<T_>::invoke(t);
}

int main(void) {
    Type<int> t_i;
    apply<add_pointer>(t_i);
}

If you can't change them directly, create functors that forward everything to the right function through a static constexpr member method.

skypjack
  • 49,335
  • 19
  • 95
  • 187
1

I am just asking about how to do "template < typename > bool Function_" as the bool part is invalid in c++ currently.

As far I know, template-template arguments are a completely different thing. They are intended for containers, not for functions. So class, not bool.

here is an example of why I can't pass the "is_pointer" to the function

Your example doesn't work because add_pointer is a template function, so when you call

apply(add_pointer, t_i);

the compiler doesn't know which version (which type T) of add_pointer to use.

A solution can be explicit it, as in the following simplified example

#include <tuple>
#include <iostream>

template <typename T>
constexpr auto add_pointer(std::tuple<T>) noexcept
 { std::cout << "add_pointer" << std::endl; return 0; }

template <typename F, typename T>
constexpr auto apply(F f, std::tuple<T> t) noexcept
 { return f(t); }

int main(void)
 {
   std::tuple<int> t_i { 1 };

   apply<int(*)(std::tuple<int>)>(add_pointer, t_i);
 }

but I understand that explicating int(*)(std::tuple<int>) is a big pain in the ass.

You can simplify a little using the fact that you pass t so you can deduce the type of the argument received by the function, but (for a generic solution) I don't know how to avoid to explicit the return type of the function (maybe it's possible, but (in this moment) I don't know.

So you can simplify the call as follows

apply<int>(add_pointer, t_i);

and the following is a little more general example

#include <tuple>
#include <iostream>

template <typename ... Ts>
constexpr auto add_pointer(std::tuple<Ts...> const &) noexcept
 { std::cout << "add_pointer" << std::endl; return 0; }

template <typename R, typename ... Ts, 
          typename F = R(*)(std::tuple<Ts...> const &)>
constexpr auto apply(F f, std::tuple<Ts...> t) noexcept
 { return f(t); }

int main(void)
 {
   std::tuple<int> t_i { 1 };

   apply<int>(add_pointer, t_i);
 }
max66
  • 65,235
  • 10
  • 71
  • 111
  • Thankyou for your help but it really isn't the implementation I'm after, I'm using my own tuple which is just a type tuple no values, and then I pass a templated function or variable which is then evaluated with all the different types in a Tuple of types. – Fletcher Blight Jul 13 '17 at 00:23