Tuesday 16 April 2019

c++ - Why is a template not recognized as instantiatable through template?

I'm trying to arbitrarily "bind" template parameters but have run into an elegance problem.




To cut straight to the underlying problem, gcc 6.2 has a problem with the following but logically I see no issue with it...



template P, typename A, typename B>
struct foo {
static constexpr bool value = P::value;
};

template

struct bar {
static constexpr bool value = true;
};


... foo given bar such as foo should result in the instantiation of bar (which is valid), who's value member is true and therefore foo::value is likewise true. Effectively, this should (in my mind) result in instantiated structs conceptually akin to...



struct bar {
static constexpr bool value = true;
};


struct foo {
static constexpr bool value = bar::value; //which is true
};


You can see this concept in action (or rather the error) here https://godbolt.org/g/lT9umg.



Back to the begining now, first I tried the following...




template
struct type_list { };

template typename Tmpl, typename...Ts>
struct bind_template {
template
using type = Tmpl;
};


template typename Predicate, typename...Ts>
struct has_matching_type {
private:
template typename, typename, typename=void>
struct helper: std::false_type { };
template typename P, typename U, typename...Us>
struct helper, typename std::enable_if::value>::type>: std::true_type { };
template typename P, typename U, typename...Us>
struct helper, typename std::enable_if::value>::type>: helper> { };
public:

static constexpr bool value = helper>::value;
};

template
using has_type = has_matching_type::template type, Ts...>;


Later I might try to instantiate through has_type such as...




cout << has_type::value << endl;


However, as I pointed out gcc 6.2.0 complains because it doesn't seem to recognize that, once resolution is done, the template instantiation is pragmatically equivalent.



Simply knowing the number of template parameters and specializing for that exact number solves the problem. If I specialize bound_template keeping std::is_same in mind...



template typename Tmpl, typename T>
struct bind_template {

template
using type = Tmpl;
};


... we suddenly compile and evaluate compile-time no problem because gcc sees bind_template::type as taking one type parameter exactly.



Obviously, abstracting this concept out to allow for any template parameters, such as integral constants and not just types, is a fundamental issue regardless of compiler. Simply focusing on types for a minute though, my question is multiple:





  1. Am I missing something here conceptually and the compiler is actually doing exactly what should be obvious to me?

  2. If not, is this in violation of C++11 standards, not directed by standards, or is it a compiler dependency?

  3. Is there some elegant way I can get around this regardless of the answers to my first two questions?



Functionally, the real question (particularly if this is an unavoidable issue in C++11) is...



Is there some elegant way I can abstractly bind templates without having to specialize for every case (the simplest here being n number of types)?



Just being able to get an answer to questions 1 or 3 would be great. Question 3 is the most important because at the end of the day it's what works that matters.




Obviously, I can specialize (as shown above). A big problem though is that even the following doesn't seem to work (at least according to this online compiler)...



template class Tmpl, typename... Ts>
struct bind_helper {
template
struct type: Tmpl { };
template
struct type: Tmpl { };
template

struct type: Tmpl { };
template
struct type: Tmpl { };
};


This means that, not only would I have to generate a bunch of parameters, but I'd have to match the outer parameters as well via complete bind_template specialization. This quickly becomes (actually is) a binomial problem.



Extending this concept further (but still keeping to types), I was planning to next implement "placeholders" the same way std::bind uses placeholders (which would have worked rather elegantly because I would have just peeled and rejoined the list at the index). Obviously this is too much of a mess to proceed without a more abstract approach available.

No comments:

Post a Comment

php - file_get_contents shows unexpected output while reading a file

I want to output an inline jpg image as a base64 encoded string, however when I do this : $contents = file_get_contents($filename); print &q...