In a C ++ template function, why does a dependent function call give a "not declared" error?

Inside the C ++ template function foo (), calling to :: bar (TT *) gives the following error in gcc 4.4.3:

g++ -o hello.o -c -g hello.cpp
hello.cpp: In function 'void foo(std::vector<TT*, std::allocator<TT*> >&)':
hello.cpp:8: error: '::bar' has not been declared

Here's the abusive code:

// hello.cpp

#include <vector>

template<typename TT> void foo(std::vector<TT*> &vec)
{
    TT *tt;
    ::bar(tt);
    vec.push_back(tt);
}

class Blah
{
};

void bar(Blah *&)
{
}

int main(int argc, char *argv[])
{
    std::vector<Blah*> vec;
    foo(vec);

    return 0;
}

C ++ distinguishes between characters that depend on the template parameter (here, here), and those characters that are independent and can be immediately evaluated.

Obviously, the compiler believes that the call to my :: bar (TT *) is independent and tries to solve it immediately. Similarly, this function callsdepending on TT, because the function call takes a parameter of type TT *, so the compiler must wait until the instance foo (vec) resolves :: bar (TT *).

Is this a gcc bug or am I missing something subtle in C ++ templates?

EDIT: :: bar(), , . , main() TT = Blah TT = Argh. 35 28 ( -). line 8.

# 2: .

EDIT # 3: , . (tt) (Blah *). , . ( ).

// hello.cpp
#include <vector>

class XX {};
void bar(XX*) {}

class CC {
public:
    void bar();
    void bar(int *);
    void bar(float *);

    template<typename TT> static void foo(std::vector<TT*> &vec);
};

template<typename TT>
void CC::foo(std::vector<TT*> &vec) {
    using ::bar;
    TT *tt;
    bar(tt);
    vec.push_back(tt);
}

class Argh {};
void bar(Argh *&aa) { aa = new Argh; }

class Blah {};
void bar(Blah *&bb) { bb = new Blah; }

int main(int argc, char *argv[]) {
    std::vector<Blah*> vec;
    CC::foo(vec);
    return 0;
}
+5
6

- , , .

++ 03 ::bar . , - - , . , id- (14.6.2.2/3 ), . ::bar . bar(tt), ++ 03 14.2.6

:

postfix-expression ( expression-listopt )

, , (14.6.2.2).

::, .

, ::, - , foo - CC - CC:: bar (...), , :: bar (TT *), CC:: bar (...). , :: , , , ::

- .

namespace dummies { void f(); }
template<typename T>
struct S {
  void f();
  void g() { 
    using dummies::f; // without it, it won't work
    f(T()); // with ::f, it won't work
  }
};

struct A { };
void f(A) { } // <- will find this

int main() {
  S<A> a;
  a.g();
}

ADL , . , - , ADL , .

, -, : Stroustrup T++ PL Sp Ed, C.13.8.1, Dependent Names: " , , "

Stroustrup , , , ++. 100%, . gory ​​ ISO.

, , . IS . 1996 , .

, , , , , , .

[...]

[: , T, :

  • , T (temp.deduct). , f (T), f (Array) f (const T *).

  • T. , f (T (1)), f (t), f (g (t)) f (& t), , t T.

, :

template<class T> class Z {
public:
        void f() const
        {
                g(1); // g() not found in Z context.
                      // Look again at point of instantiation
        }
};

void g(int);
void h(const Z<Horse>& x)
{
        x.f(); // error: g(int) called by g(1) does not depend
               // on template-argument ``Horse''
}

x.f() :

void Z<Horse>::f() { g(1); }

g (1) g (int), - , g (int) , x.f() .

:

void h(const Z<int>& y)
{
        y.f(); // fine: g(int) called by g(1) depends
               // on template-argument ``int''
}

y.f() :

void Z<int>::f() { g(1); }

g (1) g (int), - pl- int, y.f() , g (int) . ]

, , (, n3126 " " [temp.names]/p4 , " " " " ).

+5

14.7.2 ++:

:

    postfix-expression ( expression-listopt )

, , -id name, (14.7.2.2).

::b id, . ::, , , . , , bar , .

+5

Intel ++ 11.0 , , :

#include <vector>
#include <iostream>

// *********************
// forward declare in the global namespace a family of functions named bar
// taking some argument whose type is still a matter of speculation
// at this point
template<class T>
void bar(T x);
// *********************

template<typename TT>
void foo(std::vector<TT*> &vec)
{
   TT *tt;
   ::bar(tt);
   vec.push_back(tt);
}

class Blah
{
  public:
};

void bar(Blah *x)
{
  // I like output in my examples so I added this
  std::cout << "Yoo hoo!" << std::endl;
}

// **********************
// Specialize bar<Blah*>
template<>
inline
void bar<Blah*>(Blah *x) { ::bar(x); }
// **********************

int main(int, char *)
{
  std::vector<Blah*> vec;
  foo(vec);

  return 0;
}
+2

, - :

// hello.cpp

#include <vector>


class Blah
{
public:

};

void bar(Blah *&)
{ }

template<typename TT> void foo(std::vector<TT*> &vec)
{
    TT *tt;
    ::bar(tt);
    vec.push_back(tt);
}


int main(int argc, char *argv[])
{
    std::vector<Blah*> vec;
    foo(vec);

    return 0;
}
+1

- . , -. , , ? , , , , , ( ) .

// hello.cpp

#include <vector>

void bar(); // Comeau bails without this.

template<typename TT> void foo(std::vector<TT*> &vec)
{
    TT *tt;
    ::bar(tt);
    vec.push_back(tt);
}

class Blah
{
};

void bar(Blah *&)
{
}

int main(int argc, char *argv[])
{
    std::vector<Blah*> vec;
    //foo(vec); - instanting it is certainly an error!

    return 0;
}
+1

VS2005. , gcc. ( , , , - .)

gcc, bar foo, bar :

void bar(float *) {
}

template<typename TT> void foo(std::vector<TT*> &vec)
{
    TT *tt;
    ::bar(tt);
    vec.push_back(tt);
}

void bar(int *) {
}

int main(int argc, char *argv[])
{
    std::vector<int*> vec;
    foo(vec);

    return 0;
}

gcc int *:

error: int * float * 1 void (float *)

, gcc , .

, :: bar(tt), , , . , , .

0

All Articles