6

Okay I'm going to give a simple example of my problem:

void Increment(Tuple<int, int>& tuple) {
    ++tuple.Get<0>();
}

int main() {

    Tuple<int, int> tuple;

    tuple.Get<0>() = 8;

    Increment(tuple);

    printf("%i\n", tuple.Get<0>()); // prints 9, as expected

    return 0;

}

This compiles just fine, and all is peachy. The Increment function just increments the first element in the tuple, and then I print that element. However, wouldn't it be nice if my Increment function could be used on any kind of element?

template <typename T>
void Increment(Tuple<T, T>& tuple) {
    ++tuple.Get<0>(); // <-- compile ERROR
}

int main() {

    Tuple<int, int> tuple;

    tuple.Get<0>() = 8;

    Increment<int>(tuple);

    printf("%i\n", tuple.Get<0>());

    return 0;

}

My second example spits out the following error at compile-time:

error: expected primary-expression before ')' token

I'm at my wits end trying to figure out why this causes problems. Since the template parameter is 'int', the generated code should be identical to my hard-coded example. How can I get this to work?

nonoitall
  • 1,232
  • 1
  • 15
  • 25
  • 1
    The ugliness and trickiness of the usage as shown in GMan's answer is probably the reason why both std and boost tuples have a free `get` function: `++get<0>(tuple);` – UncleBens Dec 30 '10 at 12:11

2 Answers2

12

It should be:

++tuple.template Get<0>();

In the same way you need typename to specify a type qualified from a dependent type, you need template to specify a template function qualified from a dependent type.

GManNickG
  • 494,350
  • 52
  • 494
  • 543
  • Worked brilliantly! I can't believe after all these years of using C++ that I'd never heard of that. Guess I don't use templates often enough. Thanks! – nonoitall Dec 30 '10 at 11:09
  • @nonoitall: It's lesser known, for some reason. (Also because many people use NSVC, and it works without it, so people never encounter the problem in the first place.) – GManNickG Dec 30 '10 at 11:11
  • @GMan : MSVC++ is obviously non-portable then, right? (in this context) – Nawaz Dec 30 '10 at 11:20
  • @Nawaz: Well that would have to do with the binary itself, not what it does. (MS Word is non-portable, for example.) I think what you mean is *non-compliant*; and that, I'd argue, is ambiguous. It *does* accept the well-formed code as well, so it's compliant in that regard, but it doesn't diagnose ill-formed code like it should, so it's non-compliant in that regard (it can be seen as a compiler extension, allowing ill-formed code). I'd lean towards no, though, since when we say "is it compliant" we usually mean "does it follow *all* the standard" and not "does it accept all well-formed code". – GManNickG Dec 30 '10 at 11:25
  • @GMan : thanks for the nice explanation, and correct usage of terminologies. :-) – Nawaz Dec 30 '10 at 11:31
  • @GMan: I have to disagree. In my opinion, if you write code exactly Standard, and the compiler accepts it, then the compiler is portable and conformant. If you don't have to change your code between compilers, then that is the definition of portable, and this does not break portability, although it does allow non-portable code. – Puppy Dec 30 '10 at 11:31
  • @Dead: Portability and compliance are not the same thing. This seems rather contradictory: "and this does not break portability, although it does allow non-portable code." Do you mean non-compliant? – GManNickG Dec 30 '10 at 11:32
  • @GMan : What I meant by "portable", is the portability of the source, not the binary. Binaries are often non-portable (between different compilers, and even between different version of same compiler) even if the sources are standard conformant! – Nawaz Dec 30 '10 at 11:35
  • @Nawaz: Okay. I think in this case, then, portability is both vague and completely exclusive from compliance. Compliance is compiler-independent, and based on the language standard, while portability depends precisely on which compilers vendors and versions we test it on. There's no necessary causal link between the two, because compilers are all (in my experience) non-compliant in some aspect, so having compliant code doesn't imply you have portable code; nor does having portable code imply it's compliant (for example, your selection of compilers could all support the same extension). – GManNickG Dec 30 '10 at 11:39
  • @GMan: Portability is defined as accepting all code permitted by the Standard. If MSVC does accept all code defined as valid by the Standard, then it is portable. Allowing extensions makes the code non-portable as it does not fall into the realm of code defined as valid by the Standard. You're confusing the *compiler* being portable with the *source* being portable. Non-portable extensions are not non-compliant, because the Standard doesn't say that you can't extend the language. – Puppy Dec 30 '10 at 11:43
  • @GMan : since by "portable" I meant what I said in the previous comment, I should have used "compliance" in my very first post. That is less ambiguous. :-) – Nawaz Dec 30 '10 at 11:47
  • @Dead: 'Portability' is a word, and we can define it to be anything we like. Obviously we're operating with a different definition: mine concerns the portability of *code*, while yours is the portability of the *compiler*. Unfortunately, I don't follow what you're saying because of sentences like "Allowing extensions makes the code non-portable". What is "the code"? (1/2) – GManNickG Dec 30 '10 at 11:48
  • And what does it mean for a portion of *code* to become non-portable, to you? (You never defined this; your definition concerns the portability of a compiler, evidenced by "If MSVC does accept all code defined as valid by the Standard, then it [MSVC] is portable".) I'm afraid I need clarification. (2/2) – GManNickG Dec 30 '10 at 11:49
4

Since GMan already gave you the correct answer, one thing you can still do is : you can simply write Increment(tuple) instead of Increment<int>(tuple) (the latter syntax looks a bit complex). Compiler is intelligent enough to infer the function-template-type from the type of tuple.

See this : http://www.ideone.com/juNOg

Community
  • 1
  • 1
Nawaz
  • 353,942
  • 115
  • 666
  • 851