You may receive a "C3767" error message when you access a friend function with an argument of type nested class in Visual C++ .NET 2003 or in Visual C++ 2005 (814793)



The information in this article applies to:

  • Microsoft Visual C++ 2005 Express Edition
  • Microsoft Visual C++ .NET (2003)

SYMPTOMS

When you use Microsoft Visual C++ .NET 2003 or Microsoft Visual C++ 2005 to access a friend function with an argument of type nested class that is in an enclosing class, you may receive the following error messages:
error C3767: '==' matching function is not accessible could be the friend function at 'path to the code file' : '==' [may be found via argument-dependent lookup]
error C2676: binary '==' : 'A::B' does not define this operator or a conversion to a type acceptable to the predefined operator
When you receive this error, Argument-dependent lookup (which is also known as Koenig lookup) is not working for the argument type as a nested class.

CAUSE

According to the International Organization for Standardization (ISO) C++ standards (ISO/IEC 14882), if an argument type is of class type, the associated classes are the class itself and its direct and indirect base classes. Therefore, associated classes do not include any classes where the class or the struct is nested.

RESOLUTION

In the example code in the "More Information" section of this article, the operator overload == is a friend function:
	friend bool operator==(B, B){return false;}
The friend function is declared in the scope of struct A and outside the scope of struct B. According to ISO C++ standards, the name is not visible in the surrounding scope. Therefore, you receive the error that is listed in the "Symptoms" section of this article.

However, the International Organization for Standardization (ISO) introduced a mechanism to make such operators work and found that Argument-dependent lookup may be used. This mechanism is named "inline friend definitions of operators applying to the class." Accordingly, the rule is that friend declarations are visible when they are found through Argument-dependent lookup because an argument of the call is associated with a class where the function is a friend of the class.

The example code in the "More Information" section of this article violates this rule. However, you can modify the same example by moving the overload operator for == in the declaration of struct B:
struct A { 

	struct B { 
		friend bool operator==(B, B){return false;} 
	}; 

}; 

bool operator!=(A::B b0, A::B b1) 
{ 
	return !(b0==b1); 
}

STATUS

This behavior is by design.

MORE INFORMATION

With Argument-dependent (Koenig) lookup, when a function is called, the namespaces where the function parameters reside are taken into account to determine if that function is visible in the current scope.

Argument-dependent lookup examines types of all arguments in a function, and the associated namespaces and classes or structs are collected. The name of the function is then looked up in all the namespaces and classes or structs.

The following code example compiles in Microsoft Visual C++ .NET 2002 because the friend function declaration is exported to the enclosing nonclass scope. In this case, the enclosing nonclass scope is the global scope:
#include <iostream>

struct A
{
				struct B
			{
		
			};
	friend bool operator==(B, B){return false;}
};

	bool operator!=(A::B b0, A::B b1)
	{ 
		return !(b0==b1);
 //error C3767: '==' matching function is not accessible could be the friend function [may be found via argument-dependent lookup]
	}

	
	int main() {
		
		return 0;
	}
Note You must add the common language runtime support compiler option (/clr:oldSyntax) in Visual C++ 2005 to successfully compile the previous code sample. To add the common language runtime support compiler option in Visual C++ 2005, follow these steps:
  1. Click Project, and then click <ProjectName> Properties.

    Note <ProjectName> is a placeholder for the name of the project.
  2. Expand Configuration Properties, and then click General.
  3. Click to select Common Language Runtime Support, Old Syntax (/clr:oldSyntax) in the Common Language Runtime support project setting in the right pane, click Apply, and then click OK.
For more information about the common language runtime support compiler option, visit the following Microsoft Web site:

/clr (Common Language Runtime Compilation)
http://msdn2.microsoft.com/en-us/library/k8d11d4s.aspx

To reproduce this behavior, compile the code sample in the "More Information" section of this article by using Visual C++ .NET 2003 or Visual C++ 2005. You receive the error that is described in the "Symptoms" section of this article. This error occurs for the following reasons:
  • Visual C++ .NET 2003 complies with 98 percent of the ISO C++ standards. That is a higher level than by any previous version of Visual C++. Visual C++ .NET 2003 also contains new language support for features such as Koenig lookup.
  • In Visual C++ .NET 2003, no more friend declarations are exported to the nonclass scope. Instead, overloaded friend operators are resolved with the help of Argument-dependent lookup.
Therefore, in Visual C++ .NET 2003, the compiler strongly adheres to the rule that is specified in the "Resolution" section of this article.

REFERENCES

For additional information about Koenig lookup, click the following article number to view the article in the Microsoft Knowledge Base:

242190 BUG: Full Koenig Lookup Works Only for Operators

For more information about improvements in Visual C++ .NET 2003, visit the following Microsoft Developer Network (MSDN) Web site:

Modification Type:MajorLast Reviewed:1/11/2006
Keywords:kbprb kberrmsg kbLangCPP kbCPPonly kbCompiler KB814793 kbAudDeveloper