11

Is there a compiler or standalone preprocessor which takes C++ files and runs a template expansion pass, generating new C++ code with expanded template instantiations?

I remember such a tool in the mid-90s when templates were still new and experimental, and the preprocessor was a way to do template programming with compilers without native template support.

This is a lot more complicated than a macro-processing step since it would likely require parsing and tokenizing the code to understand the contexts.

My hope is to use such a tool when writing OpenCL code. OpenCL is C++, but does not support templates. I'm hoping I can write templates, even simple ones like with integer or bool only arguments, and have some tool pre-parse the file and go through and find the use of the templates and expand the invocations and give me new C++ code that the OpenCL compiler can understand.

Even a very limited tool could be useful, it does not need to support every template quirk, nor even support multiple modules or anything.

The alternative: #define macros everywhere.. uglier, unsafe, less efficient, and less versatile.

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
SPWorley
  • 11,550
  • 9
  • 43
  • 63
  • 1
    OpenCL's language is based on C99 syntax, not C++ according to the page you linked. – Evan Teran Jul 16 '09 at 19:33
  • AMD do some extension to openCL, you could develop template codes if you aim for the AMD devices only.It is a pain that we could not use template to develop our algorithms. – StereoMatching Apr 18 '13 at 18:19

3 Answers3

10

Comeau C++ can "compile" C++ to C. This would seem to be close to your goal, as OpenCL does not support C++ – it's much closer to C.

ephemient
  • 198,619
  • 38
  • 280
  • 391
1

C++ Insights (https://cppinsights.io/) is able to do this (and more generally expansion of "high-level" syntax-sugary C++ constructs. It is based on Clang so it has an understanding of the code which is as good as possible, and supports latest standards.

It will for instance expand

extern "C" void printf(...);
template<typename T>
int foo(T t)
{
  if constexpr(sizeof(T) == 4) {
    printf("int: %d", t);
  }
  else {
    printf("something else: %d", (int)t);
  }
}

int main()
{
    const char arr[10]{2,4,6,8};

    for(const char& c : arr)
    {
      foo(c);
    }
}

into

extern "C" void printf(...);
template<typename T>
int foo(T t)
{
  if constexpr(sizeof(T) == 4) {
    printf("int: %d", t);
  }
  else {
    printf("something else: %d", (int)t);
  }
}

/* First instantiated from: insights.cpp:19 */
#ifdef INSIGHTS_USE_TEMPLATE
template<>
int foo<char>(char t)
{
  if constexpr(false) {
  } else /* constexpr */ {
    printf("something else: %d", static_cast<int>(t));
  } 
  
}
#endif


int main()
{
  const char arr[10] = {2, 4, 6, 8, '\0', '\0', '\0', '\0', '\0', '\0'};
  {
    char const (&__range1)[10] = arr;
    const char * __begin1 = __range1;
    const char * __end1 = __range1 + 10L;
    for(; __begin1 != __end1; ++__begin1) {
      const char & c = *__begin1;
      foo(c);
    }
    
  }
  return 0;
}
Jean-Michaël Celerier
  • 7,412
  • 3
  • 54
  • 75
0

There is no such tool - templates are part of the language, not some pre-processor pass - they are processed by the compiler, just like other code.

  • Yes.. such a tool would indeed need to parse the C++. That's why it's more complicated than a macro preprocessor. – SPWorley Jul 16 '09 at 19:36
  • Well, like I say, no such thing exists to my knowledge. I can't see how it could process the templates and leave the "non-template" code untouched. –  Jul 16 '09 at 19:38
  • @Neil: the very first c++ compilers simply converted c++ code to valid c and compiled it using a c compiler. Certainly this is no longer the case, but used to be fairly usual. – Evan Teran Jul 16 '09 at 19:58
  • @Evan I know - I was a user of cfront from the E release onwards. However, the original question said that he wanted to expand the templates but leave the the other C++ code alone, producing a new C++ program, which cfront (and comeau) can't do. It now turns out he wants something different - such is life. –  Jul 16 '09 at 20:03
  • 2
    @Evan Teran: The very first C++ compilers didn't compile C++ as we know it. They compiled the very first versions of C++, which was vastly different. ;) – jalf Jul 16 '09 at 20:09
  • As far as I know a `'processor'` takes all templates and replaces them by instantiations. So if CallMethod(2, 3) is called, the declaration of CallMethod(Template t1, Template t2) is replaced by CallMethod(int t1, int t2). **After** `'processor'` removes templated code, the further C++ compiler runs. So couldn't one say that `'processor'` **is** a pre-processor? Cause apart from textual replacement I don't see anything else the `'processor'` needs to do. – mercury0114 Aug 06 '16 at 02:31