7

Assume that the parameters of functions representing operations of the relational algebra are represented by individual types: structs or classes. An operation such as (natural) join will have parameters of two types (T1, T2) as inputs and produce a return value of a third type (T3). There is a relationship between types T1, T2 and T3 which can in theory be known and checked at compile time. Is there a way to do that using C++ templates?

Example: assume these input types (the CJDate supplier data):

struct supplier {
  string sid;
  string sname;
  integer status;
  string city;
}
struct supplierpart {
  string sid;
  string pid;
  integer qty;
}

This is the output type:

struct ssp_join {
  string sid;
  string pid;
  integer qty;
  string sname;
  integer status;
  string city;
}

Is there any strategy that would (say) allow the output type to be generated from the inputs using templates and thus be statically type checked?

Disclosure: I'm an experienced C++ programmer and I currently have no idea how to either solve this problem or prove that it can't be done. A solution in some other language would be equally interesting.


After some further investigation, it seemed to me that key missing feature might be the kind of metaprogramming that means the ability to execute arbitrary code at compile time, prior to type resolution. The D language seems to have that. I wonder if the C++ committee are considering it.

  • Re : other languages; Haskell should fit the bill if I understand what you want. But I need to pour some coffee into myself, first. Then I'll read your q again :-) – Francesco Jun 27 '16 at 5:28
  • Have you tried something along the lines of template <class T1, class T2> struct Union : public T1, T2 { Union(const& T1 a1, const& T2 a2) : T1(a1), T2(a2) {} };? The biggest trouble I see would be the duplication of the sid member, and thus having to specify explicitly which one you want. – Bart van Ingen Schenau Jun 27 '16 at 7:12
  • @Francesco - Oleg Kiselyov's "HList" heterogenous list implementation can do it, but it uses a rather long list of extensions, many of which are rather advanced... the critical one seems to be DataKinds, which allows among other things to define a type which is a list of types. Using this and TypeFamilies you can define the type of a function that joins two heterogenous lists together. But it's not exactly plesent... – Jules Jun 27 '16 at 21:01
  • 1
    @Francesco: yes it seems so, but for a Haskell dabbler that's quite a challenging place to go. – david.pfx Jun 28 '16 at 6:04
  • 1
    @Francesco: it seems Haskell 8.0 is on the way to something better, but it could be a while yet. Meanwhile it seems that there are no widely used languages that can do this out of the box. – david.pfx Jul 3 '16 at 14:43
6

What you're talking about will not be directly possible in C++ until we get some form of both reflection introspection and reflection-based generation of types. So you're going to have to wait for a while.

The closest you can get right now is to employ inheritance:

template<typename T1, typename T2>
struct joined : public T1, public T2
{
};

Of course, this would cause you to have two separate sid members.

Indeed, most of the current attempts at solutions (tuple typelist concatenation) run into that same problem: how to remove duplicate entries.

You could do it with tuple concatenation if you used some special tag applied to each tuple element to give it a "name" of some kind. You could do that with something like this:

template<typename T, typename TagType>
struct tagged_type
{
  T t;
  using Tag = TagType;
};

//Various tag names
struct sid{};
struct sname{};
struct status{};
struct city{};
struct pid{};
struct qty{};

using supplier = tuple<
  tagged_type<std::string, sid>,
  tagged_type<std::string, sname>,
  tagged_type<int, status>,
  tagged_type<std::string, city>>;

using supplierpart = tuple<
  tagged_type<std::string, sid>,
  tagged_type<std::string, pid>,
  tagged_type<int, qty>>;

You can even make an alternate form of std::get that works by tag-name, to make it easier to access the tuple: get<sid>(tpl) and so forth.

From here, you then have to do a very complicated bit of metaprogramming where you concatenate the two tuples, but without duplicating entries.

  • Re So you're going to have to wait for a while: You're going to have to wait a long while. While C++ does not have a BDFL, it comes close to that in the persona of Bjarne Stroustrup, the inventor of C++. Stroustrup did not / does not like reflection/introspection. He thinks it's a code smell, so by design it is not a part of the language. It turns out that one can get some amount of reflection/introspection via SFINAE, but even that capability is limited compared to other languages where the BDFL thinks reflection and introspection are good ideas. – David Hammen Jun 27 '16 at 12:52
  • @DavidHammen: If that's true, why is the C++ committee actively pursuing reflection? There's an entire study group devoted to the subject. They are working on a reflection TS that's likely to be complete in the next year or two. Now, it won't have type generation, as the first phase is focused primarily on introspection. – Nicol Bolas Jun 27 '16 at 12:56
  • That's because C++ does not have a true BDFL who can nix every proposal he/she doesn't like. If C++ truly did have a BDFL, we would have to wait for that BDFL to die. How long we'll have to wait is a different matter. From what I've read, C++1z (C++17) is a bit of a disaster. We are not going to get the "good stuff" that other languages have taught are indeed "good stuff". How long one has to wait to be able to use that "good stuff" is yet another question. There are organizations (lots and lots of them) that use C++ but do not allow C++11/14 constructs. – David Hammen Jun 27 '16 at 13:04
  • 1
    @DavidHammen: "From what I've read, C++1z (C++17) is a bit of a disaster." Yes, it's so disastrous, being able to use if constexpr and have guaranteed copy elision, to be able to have constexpr lambdas and structured binding of tuples. Or any number of the dozens of other C++17-slated features. It may not be radically world-shaking, but it's hardly a "disaster". – Nicol Bolas Jun 27 '16 at 13:28
  • Okay, maybe not a disaster. Just mostly disappointing. Over a year ago, Stroustrop wrote "people will be most disappointed unless we deliver something major" (with C++17). How is Stroustrop's top ten list for C++17 faring? – David Hammen Jun 27 '16 at 13:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.