I can't think of a way to do it. On the other hand, I can't
understand why you want to do it in the first place. What are you
trying to accomplish with all this running around?
The purpose is to simplify notation for a type-generic macro. E.g.
#define STRING_TO_ARG(s) [[some compiler dependent if-else to expand
depending on type]]
Looks pretty magical to me. C is a statically-typed language,
by which I mean that every expression's (and sub-expression's) type
is known at compile time and immutable thereafter. There is no run-
time type information, except possibly for extra-linguistic stuff
carried around for the benefit of debuggers and the like (and not
accessible to the C language).
Furthermore, the preprocessor operates before the notion of
"type" even comes into existence. When the preprocessor makes its
transformations on the source, it's dealing with tokens that have
no meanings attached yet. `int' and `printf' and `12.34' are just
lexically-identified globs of goo, not keywords and identifiers and
constants. Thus, the preprocessor can't make tests of types, since
there are no types to test.
The only time when types can be tested -- and I mean "tested"
in a rather weak way -- is in the intermediate period after the
preprocessor finishes and before the program runs. Somewhere in
that span, the compiler recognizes that `12.34' is a `double' and
that `x' is a `whatever x is', so (for example) it knows how and
whether to perform promotions, whether a `+' specifies floating-
point, integer, or pointer addition, and so on. But there's no way
to extend this repertoire of tests into something the code can use,
except maybe by forcing an error message from a type mismatch (e.g.,
calling `sin(stdout)' "tests" whether `stdout' is something that
will convert to a `double').
So I think you're out of luck, unless you really can work magic.
Is "C. Comren" a nom de plume for "Harry Potter?"
#define beginswith_(s1,n1,s2,n2) (n1>= n2&& memcmp(s1,s2,n2) == 0)
#define beginswith(s,t) beginswith_(STRING_TO_ARG(s),STRING_TO_ARG(t))
Then I can write
beginswith(s,"pattern");
beginswith(s,t);
Since "pattern" is a compile-time constant, it is expanded to
"pattern",7. If I make beginswith_ into a function, the expressions
are expanded correctly. However, using a function defeats my intention
of having no overhead.
"No overhead." (Sigh.) Eternal youth would be nice, too,
and perpetual motion, and the trash removal contract for El Dorado.
Perhaps you've done this, but I must ask: Have you *measured* the
"overhead" of a straightforward approach and found it wanting? Or
are you just guessing?