I was not using the latest C++ standard for a while, today I want to implement a Haskell style List in C++ and come up with something like the following:
template<typename T>
class List {
private:
std::function<std::tuple<T,List<T>>()> f;
List() {}
List(T h, List<T> t) :f([h, t]() { return std::make_tuple(h, t); }) {}
public:
typedef T item_type;
static List<T> empty();
static List<T> cons(T h, List<T> t);
template<typename N, typename C>
static auto on(N n, C c) -> decltype(N());
};
template<typename T>
List<T> List<T>::empty() {
return List();
}
template<typename T>
List<T> List<T>::cons(T h, List<T> t) {
return List([h, t](std::function<void(T, List<T>)> c) {f(c); });
}
template<typename T>
template<typename N, typename C>
auto List<T>::on(N n, C c) -> decltype(N()) {
if (f == nullptr) return n();
else {
T h;
List<T> t;
std::tie(h, t) = f();
return c(h, t);
}
}
template<typename T, typename R, typename F>
R foldr(List<T> l, F f, R b) {
return l.on([b]() { return b; }, [f, b](T h, List<T> t) { return foldr(t, f, f(t, b)); });
}
The code compiles (VC 2015, not tested yet), but makes me a while to figure out the correct grammar for the function on. This is the first time I saw something like this in C++, and the double template keyword looks strange enough to me.
Question
Is this the normal way when we declare static generic methods that uses template variable not available through the class template? Can anyone point me out some clauses in the standard?
Is this the normal way when we declare static generic methods that
uses template variable not available through the class template?
Yes, it is normal.
Can anyone point me out some clauses in the standard?
From the n4296, 14.5.2 Member templates:
A template can be declared within a class or class template; such a
template is called a member template. A member template can be defined
within or outside its class definition or class template definition. A
member template of a class template that is defined outside of its
class template definition shall be specified with the
template-parameters of the class template followed by the
template-parameters of the member template. [ Example:
template<class T> struct string {
template<class T2> int compare(const T2&);
template<class T2> string(const string<T2>& s) { / ... / }
};
template<class T> template<class T2> int string<T>::compare(const T2& s) {
}
—end example ]
Related
I have objects of type 'value' from OCaml in C++ (they are provided by some integration channel, but it is offtopic). This object contains OCaml data of some type (primitive: int, long... or structural). It can be converted to a C++ object, from OCaml int to C++ int, etc by some provided by "caml/mlvalues.h" functions like Int_val (Long_val, Bool_val ...).
I wrapped functions from "caml/mlvalues.h" by some template function T to<T>(value x) in Caml::Value namespace to improve readability. (Caml::Value::to<bool> better then Bool_val).
caml.h:
namespace Caml::Value {
template<typename T> struct CannotConvertTo { };
template<typename T> T to(value x);
caml.cpp:
namespace Caml::Value {
template<typename T> T to(value x) {
if (is_enum<T>::value) {
return static_cast<T>(to<int>(x));
}
throw CannotConvertTo<T>();
}
template<> int to<int>(value x) {
return Int_val(x);
}
template<> bool to<bool>(value x) {
return Bool_val(x);
}
}
Also 'value' can contain some structure and we can read fields of this structure by the function Field(value, index). And I trying to implement some generic implementation to convert the 'value' to tuple.
template<> tuple<T1, T2> to<tuple<T1, T2>>(value x) {
return make_tuple<T1, T2>(
to<T1>(Field(x, 0)),
to<T2>(Field(x, 1))
);
}
Of course, it is an uncompilable code because of unknown types T1 and T2. How to implement to<tuple<T1, T2>>()? Is it possible to declare something like a template of a template? Like:
template<typename T1, typename T2>
template<> tuple<T1, T2> to<tuple<T1, T2>>(value x) {
...
}
You can forward the operation from a function template to a class template and specialise the latter, leaving the former fully generic.
// base case: conversion disallowed
template <typename K>
struct convert_to
{ static K convert_to(value) = delete; };
// convert to specific types
template <> struct convert_to<int>
{ static int convert(value); };
template <> struct convert_to<bool>
{ static bool convert(value); };
template <typename L, typename R> struct convert_to<std::pair<L, R>>
{ static std::pair<L, R> convert(value); };
// function template, never specialised
template <typename K> K to(value x)
{ return convert_to<K>::convert(x); }
I have a templated class with a templated friend function declaration that is not having its signature matched when stated in a more direct, but seemingly equivalent, expression:
link to example on online compiler
#include <type_traits>
template <typename Sig> class Base;
template <typename R, typename ... Args> class Base<R(Args...)> { };
template <typename Sig, typename T> class Derived;
template <typename Sig> struct remove_membership;
template <typename T, typename R, typename ... Args>
class Derived<R(Args...), T> : public Base<R(Args...)> {
static void bar() { }
// XXX: why are these two not equivalent, and only the 1st version successful?
template <typename T2>
friend auto foo(T2 const &) -> Base<typename
remove_membership<decltype(&std::remove_reference_t<T2>::operator())>::type> *;
template <typename T2>
friend auto foo(T2 const &) -> Base<R(Args...)> *;
};
template <typename F, typename R, typename ... Args>
struct remove_membership<R (F::*)(Args...) const> {
using type = R(Args...);
};
template <typename T>
auto foo(T const &) -> Base<typename
remove_membership<decltype(&std::remove_reference_t<T>::operator())>::type> *
{
using base_param_t = typename remove_membership<
decltype(&std::remove_reference_t<T>::operator())>::type;
Derived<base_param_t, T>::bar();
return nullptr;
}
int main(int, char **) { foo([](){}); } // XXX blows up if verbose friend decl. removed.
Inside member definitions of Derived<R(Args...), T> (for example, in the body of bar()), the types match, adding to my confusion:
static_assert(std::is_same<Base<R(Args...)>, Base<typename
remove_membership<decltype(&std::remove_reference_t<T>::operator())>::type>>::value,
"signature mismatch");
Are there rules around template class template member function (and friend function) delarations and instantiations that make these preceding declarations distinct in some or all circumstances?
template <typename T2>
void foo(T2 const &)
template <typename T2>
auto foo(T2 const &)
-> std::enable_if_t<some_traits<T2>::value>;
Are 2 different overloads. Even if both return void (when valid).
2nd overload uses SFINAE.
(and yes, template functions can differ only by return type contrary to regular functions).
Your version is not identical but similar (&std::remove_reference_t<T>::operator() should be valid)
You can use the simpler template friend function:
template <typename T, typename R, typename ... Args>
class Derived<R(Args...), T> : public Base<R(Args...)> {
static void bar() { }
template <typename T2>
friend auto foo(T2 const &) -> Base<R(Args...)>*;
};
template <typename T>
auto foo(T const &) -> Base<void()>* // friend with Derived<void(), U>
{
using base_param_t = typename remove_membership<
decltype(&std::remove_reference_t<T>::operator())>::type;
Derived<base_param_t, T>::bar();
return nullptr;
}
Demo
but you have then to implement different version of the template foo.
The problem can be reduced to:
template<class T>
struct identity {
using type=T;
};
class X {
int bar();
public:
template<class T>
friend T foo();
};
template<class T>
typename identity<T>::type foo() { return X{}.bar(); }
int main() {
foo<int>(); // error: bar is a private member of X
}
Even though we know identity<T>::type is always T, the compiler doesn't know that and would be wrong to assume so. There could be a specialization of identity<T> somewhere later in the code that resolves to some type other than T.
Therefore when the compiler sees the second declaration of foo it won't assume that it is the same friend foo declared before.
I'm trying to implement tuples with template metaprogramming, but am having problems with the indexing function get. The implementation of Tuple type is this:
template<typename A, typename... B>
class Tuple : Tuple<B...> {
private:
A val;
public:
using Base = Tuple<B...>;
Base* base() {
return static_cast<Base*>(this);
}
const Base* base() const {
return static_cast<const Base*>(this);
}
Tuple(A a, B... b): Base(b...), val(a) { }
A first() {
return val;
}
};
template<class A>
class Tuple<A> {
private:
A val;
public:
Tuple(A a): val{a} {}
A first() {
return val;
}
};
The implementation of get structure is:
template<int N, class... A>
struct get {
select<N,A...> operator()(Tuple<A...> t) {
return get<N-1>()(t.base());
}
};
template<class R, class... A>
struct get<0> {
R operator()(Tuple<R, A...> t) {
return t.first();
}
};
This is the error compiler is giving me:
tuple.cpp:53:8: error: partial specialization of 'get' does not use any of its template parameters
struct get<0> {
^
1 error generated.
Why am I getting this error? How can I correct it?
Note: select<N,A...> is a type function which selects type at Nth index from A.
Your get's primary template is:
template<int N, class... A>
struct get{ ... };
your get's partial specialization is:
template<class R, class... A>
struct get<0>{ ... };
The specialization is receiving a single template argument, i.e.: 0, but the primary template above takes two template parameters:
the non-type template parameter N.
the variadic type parameter A.
Besides, how can R be deduced?
Specializing get instead as:
template<class R, class... A>
struct get<0, R, A...>{ ... };
will make possible R to be deduced: it will be deduced to the type of the first element of the passed variadic argument. For example, in:
get<0, int, float, double> foo;
R will be deduced to int.
Maybe you have to partial specialize get as follows
template<class R, class... A>
struct get<0, R, A...> {
R operator()(Tuple<R, A...> t) {
return t.first();
}
};
I mean... get<0, R, A...>, not get<0>
But you have also to modify the main get to call the following call with the correct type list, so
template<int N, typename A0, typename ... As>
struct get {
auto operator()(Tuple<A0, As...> t) {
return get<N-1, As...>()(t.base());
}
};
Otherwise you can also demand the types management to a template version of the operator() and maintain only the int N value for get
template <int N>
struct get
{
template <typename Tpl>
auto operator() (Tpl t)
-> decltype( get<N-1>()(t.base()) )
{ return get<N-1>()(t.base()); }
};
template<>
struct get<0>
{
template <typename Tpl>
auto operator() (Tpl t)
-> decltype ( t.first() )
{ return t.first(); }
};
Starting from C++14 you can avoid the decltype() part.
Off topic suggestion: avoid the use of names that can collide with std namespace names.
Maybe myGet and myTuple instead of get and Tuple.
Otherwise you can put all in a personal namespace (so myNs::get and myNs::Tuple.
I have an indexer function, and was attempting to specialize it for the standard container types, but get errors. I'm sure it's either simple or impossible, but I can't recall which. I would prefer these as a function-object, but I wasn't able to make that work either. Is it possible to specialize a template function for a template class
namespace std { //declarations of predefined indexable types
template <class T, class A> class vector;
//others are here too, but all have the same issue
}
//default indexer
template <class T>
double indexer(const T& b) { //this seems to work fine
return b.getIndex();
}
// base types
template<> double indexer<char>(const char& b) { return double(b); }
//other primitives are here too, and work fine
// standard library
template<class T, class A>
double indexer<std::vector<T,A>>(const std::vector<T,A>& b)
{ return b.empty() ? 0 : indexer(*b.cbegin()); } //line with error
error message:
error C2768: 'indexer' : illegal use of explicit template arguments
I would like for this to be specialization vs overloading, because I have a function A that takes a function object/pointer template parameter, and overloaded function A that calls the first A with a defaulted indexer.
template<class T, class function>
double A(T a, function F) { return F(a);} //complicated
template<class T>
double A(T a) {return A(a, indexer<T>);} //default wrapper
It seems highly likely this is a duplicate question, but I cannot seem to find one.
You cannot partially specialize template functions, only template classes.
use overloading instead:
namespace std { //declarations of predefined indexable types
template <class T, class A> class vector;
}
//default indexer
template <class T>
double indexer(const T& b) { return b.getIndex(); }
double indexer(const char& b) { return double(b); }
template<class T, class A>
double indexer(const std::vector<T,A>& b)
{ return b.empty() ? 0 : indexer(*b.cbegin()); }
Since functions cannot be partially specialized, I can replace the indexer functions with function objects. This seems to work fine, and solves all my problems.
namespace std { //declarations of predefined indexable types
template <class T, class A> class vector;
}
template <class T>
struct indexer {
double operator()(const T& b) const
{ return b.getIndex(); }
};
template<> struct indexer<char> {
double operator()(const char& b) const
{ return double(b); }
};
template<class T, class A> struct indexer<std::vector<T,A>> {
double operator()(const std::vector<T,A>& b) const
{ return b.empty() ? 0 : indexer(*b.cbegin()); }
};
template<class T, class function>
double A(T a, function F) { return F(a);} //complicated
template<class T>
double A(T a) {return A(a, indexer<T>());} //default wrapper
Here's a solution based solely on overloads, using C++11-style variadic templates:
template <typename T>
T print(const T & t)
{
std::cout << t << std::endl;
return t;
}
template <template <typename...> class Container, typename ...Args>
typename Container<Args...>::value_type print(const Container<Args...> & v)
{
typedef typename Container<Args...>::value_type T;
if (v.empty()) std::cout << "nil" << std::endl;
else std::cout << *v.begin() << std::endl;
return v.empty() ? T() : *v.begin();
}
If you want to be fancy and if you have access to an is_container type trait (e.g. taken from the pretty printer), you can make the container overload specific to containers, using enable_if:
template <template <typename...> class Container, typename ...Args>
typename std::enable_if<is_container<Container<Args...>>::value,
typename Container<Args...>::value_type>::type
print(const Container<Args...> & v)
{
/* ... */
}
I'm having compile time trouble with the following code:
template <typename T,
template <class T, class Allocator = std::allocator<T> > class C>
bool is_in(const C<T>& a, const C<T>& b);
template <typename T, std::vector> // HERE
bool is_in(const std::vector<T>& a, const std::vector<T>& b)
{
return false; // implementation tbd
}
...
vector<int> a, b;
cout << is_in(a,b) << endl;
The error message is (on the line marked "HERE"):
error: 'std::vector' is not a type
(of course, I have included vector from std!). Any suggestion? I fiddled with it for a while, but I'm getting to the point where I could use some help :-) I need to partially specialize the initial template declaration so that I can have the compiler switch implementations depending on the actual type of the container C (there will be a is_in for sets, one for vectors, one for ranges..., with different algorithms each time).
Thanks!
The partial specialization of a function template is not allowed by the Standard.
A simple solution is : use overload.
template <typename T>
bool is_in(const std::vector<T>& a, const std::vector<T>& b)
{
return false; // implementation tbd
}
This is overloaded function template. Its NOT partial specialization.
Or, you could do this:
namespace detail
{
template<typename T, typename C>
struct S
{
static bool impl(const C & a, const C & b)
{
//primary template
//...
}
}
template<typename T>
struct S<T, std::vector<T> >
{
static bool impl(const std::vector<T> & a, const std::vector<T> & b)
{
//partial specialization for std::vector
return false;
}
}
}
template <typename T, template <class T, class Allocator = std::allocator<T> > class C>
bool is_in(const C<T>& a, const C<T>& b)
{
return detail::S<T, C<T> >::impl(a,b);
}
Function template partial specialization is not allowed. In any case you're not using the template specialization syntax, you're actually writing an additional overload. Try this instead:
template <typename T>
bool is_in(const std::vector<T>& a, const std::vector<T>& b)
{
return false; // implementation tbd
}
If partial specialization were allowed, it would look like this instead:
template <typename T> // std::vector is not a template parameter,
// so we wouldn't put it here
bool is_in<T, std::vector>(const std::vector<T>& a, const std::vector<T>& b)
// instead, it'd appear ^ here, when we're specializing the base template
{
return false; // implementation tbd
}
I don't know if it works (as template templates are always a trouble to my mind), but what about just trying
template <typename T>
bool is_in(const std::vector<T>& a, const std::vector<T>& b)
{
...
}
as it's a specialization.
EDIT: Others have clarified on this already, but I'll add it for completeness. The above code is actually an overload and not a partial specialization, but partial function specializations aren't allowed anyway.