How to Emulate Template≪Auto X≫

Is it possible to emulate template auto X ?

After your update: no. There is no such functionality in C++. The closest is macros:

#define AUTO_ARG(x) decltype(x), x

f.bar<AUTO_ARG(5)>();
f.bar<AUTO_ARG(&Baz::bang)>();

Sounds like you want a generator:

template <typename T>
struct foo
{
foo(const T&) {} // do whatever
};

template <typename T>
foo<T> make_foo(const T& x)
{
return foo<T>(x);
}

Now instead of spelling out:

foo<int>(5);

You can do:

make_foo(5);

To deduce the argument.

Avoiding auto in template parameter lists

You have only one recourse pre-C++17, and it isn't pretty or recommended. You must turn to the preprocessor. Only that can "automatically extract the type".

#include <iostream>

template <typename C, typename T>
using Func = const T& (C::*)(void) const;

template<typename PMem, PMem f> class X;

template <typename C, typename T, Func<C, T> F>
class X<Func<C, T>, F> {};

#define MAKE_X(...) X<decltype(__VA_ARGS__), __VA_ARGS__>

struct Y { const int &getInt() const; };


int main() {
MAKE_X(&Y::getInt) x;
return 0;
}

The key part is MAKE_X. It will emit the same tokens you gave it, both as the argument to decltype and unchanged. This is a hack to extract the type of the expression automatically.

Needless to say, it's no where near as good as a proper auto parameter.

How to emulate deduction guides for template aliases?

The easy answer is to wait until C++20. It's pretty likely that class template deduction will be learn how to look through alias templates by then (as well as aggregates and inherited constructors, see P1021).


Beyond that, (1) is definitely a bad choice. But choosing between (2), (3), and (4) largely depends on your use cases. Note that for (4), deduction guides aren't inherited until P1021 either, so you'd need to copy the base class' deduction guides if you go the inheritance route.

But there's also a fifth option that you missed. The boring one:

special<float> b { x, y }; // works fine, even in C++11

Sometimes, that's good enough?

How to emulate higher order function with C++ templates?

You are looking for the concept calked currying. Look it up. Here's a quickly thrown together sample implementation:

template<template<class,class> class fn>
struct curry
{
template <class A>
struct apply1
{
template <class B>
using apply = fn<A,B>;
};
template<class A>
using apply = apply1<A>;
};

// That's it. Below is a test rig.

template <class>
struct test1 {};

template <template<class>class>
struct test2{};

// a meta function to test
template <class, class>
struct myfn {};

// same function, curried
using myfngood = curry<myfn>;

// fully applied myfngood is a type
test1 <myfngood::apply<int>::apply<char*>> t1;

// partially applied myfngood is a template
test2 <myfngood::apply<int>::apply> t2;

Is it possible to emulate template auto X ?

After your update: no. There is no such functionality in C++. The closest is macros:

#define AUTO_ARG(x) decltype(x), x

f.bar<AUTO_ARG(5)>();
f.bar<AUTO_ARG(&Baz::bang)>();

Sounds like you want a generator:

template <typename T>
struct foo
{
foo(const T&) {} // do whatever
};

template <typename T>
foo<T> make_foo(const T& x)
{
return foo<T>(x);
}

Now instead of spelling out:

foo<int>(5);

You can do:

make_foo(5);

To deduce the argument.

Pointer to class member as a template parameter

In c++17, with the addition of auto in template arguments (P0127), I think you can now do:

template<auto value>
struct MyStruct {};

template<typename Class, typename Result, Result Class::* value>
struct MyStruct<value> {
// add members using Class, Result, and value here
using containing_type = Class;
};

typename MyStruct<&Something::theotherthing>::containing_type x = Something();


Related Topics



Leave a reply



Submit