6

I'm trying to port some code written for MSVC over to compile on Clang. However it seems to be having a problem finding some template functions. Here is part of the definition of the struct that is giving me problems:

template< typename T > struct FixedVector
{
    T * ptr;
    size_t count;

    typedef T value_type;

    FixedVector():ptr(0),count(0) {}
    ~FixedVector()
    {
        DeleteArr(ptr); // Error message appears here
        count=0;
    }
// ...
}

The DeleteArr(ptr) function refers to a function defined later on, like so:

template< typename T > inline void DeleteArr( T *& ptr )
{
    delete[] ptr;
    ptr = NULL;
}

This is the error message I get on the line indicated:

error: call to function 'DeleteArr' that is neither visible in the template definition nor found by argument-dependent lookup

Looking at the full drop-down list for the error (in Xcode), the following message is at the bottom of the list:

'DeleteArr' should be declared prior to the call site or in an associated namespace of one of its arguments.

Clicking on this message brings me to the definition of the DeleteArr() function, as shown above.

This apparently compiled fine in MSVC, and from looking around at the differences between Clang and MSVC, this is due to a quirk in MSVC that doesn't require functions like this to be defined before they're used, as long as there is a definition somewhere. So I looked up this error message in the Clang documentation (relevant part is under the title "Unqualified lookup in templates") and it suggested adding a forward declaration before the template definition. So I added this above the definition for FixedVector:

template< typename T > inline void DeleteArr( T *& ptr );

However, this error message is still coming up, and that final bit of the error message (the 'should be declared prior to the call site' bit) still points to the actual definition of the function. Does anyone know what may be the problem? I'm all out of ideas as to how this is valid on MSVC. Also, since the error message can find the definition of the function, why is it saying it can't be found?

UPDATE: At the advice of the comments, I've added the implementation of DeleteArr() to where I declared it above the template. This seems to result in the same error! I'm really stumped now.

benwad
  • 6,414
  • 10
  • 59
  • 93
  • 1
    I am a bit confused if your functions are member functions or not. You do not use the resolution operator so i might be tempted to think that they are member functions. But then why to you use `template` and `inline` when defining them ? – coredump Sep 26 '12 at 09:56
  • 1
    DeleteArr is not a member of FixedVector: it is declared in a separate file used for utility functions. – benwad Sep 26 '12 at 09:58
  • The easiest fix seems to be to just move the definition up. But that doesn't explain this weird behaviour. – bitmask Sep 26 '12 at 09:59
  • Is `DeleteArr` in the same namespace ? It looks like some global function template. Also I am not sure if the compiler can deduce a forward declaration based on a template. I.e. will it try to resolve the templated forward declaration. I believe it should. I think g++ does. You can check it by writing the instantiated version of the declaration by hand. – luk32 Sep 26 '12 at 10:00
  • @benwad: Regarding your last comment: If it's declared in a separate file, maybe it's not properly included. Try declaring it just before `FixedVector`. – bitmask Sep 26 '12 at 10:01
  • Thanks for the comments - I've updated the question to reflect what I've tried. – benwad Sep 26 '12 at 10:12
  • I think the error message is pretty clear and concise. your code is faulty. MSVC is rubbish (not the only softward from that company with that property) – Walter Sep 26 '12 at 12:55

2 Answers2

8

The declaration of DeleteArr must be available to FixedVector, i.e. the definition of the former has to come before the use by the latter. This is likely related to the failure of MSVC to correctly implement the two-phase lookup.

Community
  • 1
  • 1
juanchopanza
  • 223,364
  • 34
  • 402
  • 480
1

first define DeleteArr

template< typename T > inline void DeleteArr( T *& ptr )
    {
        delete[] ptr;
        ptr = NULL;
    }

Then define fixedvector

template< typename T > struct FixedVector
{
    T * ptr;
    size_t count;

    typedef T value_type;

    FixedVector():ptr(0),count(0) {}
    ~FixedVector()
    {
        DeleteArr(ptr); // Error message appears here
        count=0;
    }
// ...
}
Ravindra Bagale
  • 17,226
  • 9
  • 43
  • 70
  • I've added the DeleteArr definition right above the FixedVector definition, but I still get that error message. Is there any other reason this could be happening? – benwad Oct 08 '12 at 09:49
  • Actually, ignore that last comment. There was a preprocessor issue keeping my definition from being seen. – benwad Oct 08 '12 at 11:24