Compiler Error C2664

'function' : cannot convert parameter number from 'type1' to 'type2'

A parameter cannot be converted to the required type. This might happen if you create an instance of a class and attempt an implicit conversion on a constructor marked with the explicit keyword.

If a temporary object is passed to a function that takes a reference to an object as a parameter, that reference must be a const reference.

If the function is called with a parameter that is not of the type that the function expects, a temporary object is created using the appropriate constructor. This temporary object is then passed to the function. In this case, the temporary object is used to initialize the reference. In earlier versions of the language, all references could be initialized by temporary objects.

To resolve C2664,

  • Recheck the prototype for the given function and correct the argument noted in the error message.

  • Supply an explicit conversion if necessary.

C2664 can also be generated if a class hides a member in one of its base classes.

For more information, see How to: Convert System::String to wchar_t* or char*.

Example

The following sample generates C2664.

// C2664.cpp
// C2664 
struct A {
   void f(int i) {};
};

struct B : public A {
   // Uncomment the following line to resolve.
   // using A::f;
   void f(A a) {};
};

int main() {
   B b;
   int i = 1;
   b.f(i);   // B::F hides A::f uncomment using declaration in B
}

The following sample generates C2664.

// C2664b.cpp
// C2664 expected
struct A {
   // Uncomment the following line to resolve.
   // A(int i){}
};

void func( int, A ) {}

int main() {
   func( 1, 1 );   // no conversion from int to A
}

The code below demonstrates this error by calling Test with a string literal. Because the parameter is an szString reference, an object must be created by the appropriate constructor. The result is a temporary object that cannot be used to initialize the reference.

// C2664c.cpp
// compile with: /EHsc
// C2664 expected
#include <iostream>
#include <string.h>
using namespace std;

class szString {
   int slen;
   char *str;

public:
   szString(const char *);
   int len() const { 
      return slen; 
   }
};

// simple reference cannot bind to temp var
void Test(szString &a) {}

// Uncomment the following line to resolve.
// void Test(const szString &a) {}

szString::szString(const char * newstr) : slen(0), str(NULL) {
   slen=strlen(newstr);
   str = new char[slen + 1];
   if (str)
      strcpy_s(str, (slen + 1), newstr);
}

int main() {
   Test("hello");
}

The compiler enforces the C++ standard requirements for applying const. The following sample generates C2664.

// C2664d.cpp
// C2664 expected
#include <windows.h>

void func1(LPCSTR &s)
{

}

void func2(LPSTR &s)
{
   func1(s);
}

int main()
{
   return 0;
}

The following demonstrates a more complex situation where C2664 is generated.

// C2664e.cpp
// compile with: /EHsc
// C2664 expected
#define _INTL
#include <locale>
#include <iostream>

using namespace std;
#define LEN 90

int main( ) {
   char* pszExt = "This is the string to be converted!";
   wchar_t pwszInt [LEN+1];
   memset(&pwszInt[0], 0, (sizeof(wchar_t))*(LEN+1));

   // Delete the following line to resolve.
   char* pszNext;

   // Uncomment the following line to resolve.
   // const char* pszNext;

   wchar_t* pwszNext;
   mbstate_t state;
   locale loc("C");  
   int res = use_facet<codecvt<wchar_t, char, mbstate_t> >
      ( loc ).in( state,
      pszExt, &pszExt[strlen(pszExt)], pszNext,
      pwszInt, &pwszInt[strlen(pszExt)], pwszNext );
   // see comment above
      pwszInt[strlen(pszExt)] = 0;
   wcout << ( (res!=codecvt_base::error) ? 
                       L"It worked! " : L"It didn't work! " )
   << L"The converted string is:\n ["
   << &pwszInt[0]
   << L"]" << endl;

   exit(-1);
}

An enum variable is not converted to its underlying type, such that, a function call will be satisfied. For more information, see enum class. The following sample generates C2664.

// C2664f.cpp
// compile with: /clr
using namespace System;
public enum class A : Char {
   None = 0,
   NonSilent = 1,
};

void Test(Char c) {}

int main() {
   A aa = A::None;
   Test(aa);   // C2664
   Test(Char(aa));   // OK
}

A bug in the midl compiler results in a wchar_t type being emitted as an unsigned short in the type library. To resolve this error, either cast the type in your C++ source code or define the type as a string in the idl file.

// C2664g.idl
import "prsht.idl";

[ object, uuid(8402B8F1-BF7F-4B49-92D4-C2B9DF4543E9) ]

interface IMyObj1 : IUnknown {
   HRESULT  teststr([in, string] wchar_t *wstr);
   HRESULT  testarr([in, size_is(len)] wchar_t wstr[], [in] int len);
   HRESULT  testbstr([in] BSTR bstr);
};

[  uuid(44463307-CBFC-47A6-8B4F-13CD0A83B436) ]
library myproj1 {
   [  version(1.0), uuid(D8622C12-5448-42B8-8F0E-E3AD6B8470C1) ]
   coclass CMyObj1 { interface IMyObj1; };
}

The following sample generates C2664.

// C2664h.cpp
#import "C2664g.tlb"
using namespace myproj1;

int main() {
   IMyObj1Ptr ptr;

   wchar_t * mybuff = 0;
   BSTR bstr = 0;
   int len;
   ptr->teststr(mybuff);
   ptr->testbstr(bstr);
   ptr->testarr(mybuff, len);   // C2664
   ptr->testarr((unsigned short *)mybuff, len);   // OK
}

C2664 is also caused if the compiler could not deduce template arguments. The following sample generates C2664.

// C2664i.cpp
#include <stdio.h>
template <class T, int iType=0>
class CTypedImg {
public:
   CTypedImg() {}
   void run() {}

   operator CTypedImg<T>& () {
      return *((CTypedImg<T>*)this);
    }
};

template <class t1>
void test(CTypedImg<t1>& myarg) {
   myarg.run();
}

int main() {
   CTypedImg<float,2> img;

   test((CTypedImg<float>&)img);   // ok
   test<float>(img);   // ok
   test(img);   // C2664
}