1

In the example below, a function f of Foo tries to access the constant defined in the base class. Since the base class type my is only defined in the header, it should not be visible in the function argument in cpp. This is correctly detected by MSVC but gcc still compiles it without problem. Which specialty of gcc that allows this?

foo.h

template<int TDegree>
class Base
{
public:
    static const int dim = 3;
};

template<int TDim> class Vector {};

template<int TDegree>
class Foo : public Base<TDegree>
{
public:
    typedef Base<TDegree> my;

    void f(const Vector<my::dim>& v) const;
};

foo.cpp

#include "foo.h"

template<int TDegree>
void Foo<TDegree>::f(const Vector<my::dim>& v) const {}

// instantiation
template class Foo<1>;

The error message with MSVC is:

<source>(21): error C2244: 'Foo<TDegree>::f': unable to match function definition to an existing declaration
<source>(21): note: see declaration of 'Foo<TDegree>::f'
<source>(21): note: definition
<source>(21): note: 'void Foo<TDegree>::f(const Vector<Base<TDegree>::dim> &) const'
<source>(21): note: existing declarations
<source>(21): note: 'void Foo<TDegree>::f(const Vector<Base<TDegree>::dim> &) const'
463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
kstn
  • 537
  • 4
  • 14
  • 6
    *it should not be visible in the function argument in cpp* Why not? Doesn't `foo.cpp` include `foo.h`? – NathanOliver Jan 18 '23 at 13:14
  • 2
    fyi [Why can templates only be implemented in the header file?](https://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file) – Richard Critten Jan 18 '23 at 13:15
  • 1
    What exactly does VC++ say is wrong? – molbdnilo Jan 18 '23 at 13:18
  • I do get an error with msvc, but not about accessiblitly of `my`, at least there is no obvious relation. It complains about defintion not matching the declaration (and then shows identical decalration vs definition ) https://godbolt.org/z/aMcnh895c. Please include your error in the quesiton – 463035818_is_not_an_ai Jan 18 '23 at 13:19
  • The definition of (templated) `Foo::f()` has a diagnosable error (will not compile) if the definition of `Foo` is not visible. Your understanding is incorrect. – Peter Jan 18 '23 at 13:19
  • @463035818_is_not_a_number it is exactly the error message. If you replace `my` in cpp by `Base` MSVC will compile. The function signature is correct, just that MSVC does not understand `my` in cpp. – kstn Jan 18 '23 at 13:22
  • why do you not want to include the error message in the question? – 463035818_is_not_an_ai Jan 18 '23 at 13:23
  • 1
    clang and gcc compile, MSVC error - live - https://godbolt.org/z/rYvTEhjGs – Richard Critten Jan 18 '23 at 13:23
  • If `my` weren't visible in the definition, there would be an error message about the name ("'my': is not a class or namespace name"). Seeing as VC++ seems to be the only compiler to reject this, I wouldn't bet on VC++ being right. – molbdnilo Jan 18 '23 at 13:24
  • @463035818_is_not_a_number that's a miss. I'll add. – kstn Jan 18 '23 at 13:25
  • not an answer, but consider this code https://godbolt.org/z/1h9fTzrYe. According to your line of reasoning this should be an error too. – 463035818_is_not_an_ai Jan 18 '23 at 13:34
  • I wan't to underline what @RichardCritten says. Don't put the implementation of the template in a cpp file. Put it in the header. – JHBonarius Jan 18 '23 at 13:34
  • @JHBonarius I heard your argument million times. But in reality, people put it in cpp for maintainance and save time. Change one line in header and the whole project recompiles. We don't want to waste time on it. In addition this code still fails with MSVC even they are all in the header. – kstn Jan 18 '23 at 13:36
  • @kstn (ignoring existing the error) - The code will only link because it has manually instantiated the template `template class Foo<1>;` in the implementation file. This manual instantiation is not be necessary if the complete implementation is visible in the header file. For templates with more parameters this manual instantiation will be a problem as the code would need to manually instantiate all possible combinations of parameter in the implementation file not where the template is used. – Richard Critten Jan 18 '23 at 13:55
  • why not simply make the example have all code in `main.cpp`. Then the issue about template implementations in a source is not only irrelevant but also not present. – 463035818_is_not_an_ai Jan 18 '23 at 14:06
  • @kstn that only works with explicit instantiation. I see you indeed added that in an edit. I wrote my comment before seeing that edit. – JHBonarius Jan 18 '23 at 14:23

0 Answers0