![]() |
| | #256 |
| Cat without Hat Join Date: Apr 2003
Posts: 8,492
|
__________________ All the buzzt! CornedBee"There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code." - Flon's Law |
| CornedBee is offline | |
| | #257 | |
| Mysterious C++ User Join Date: Oct 2007
Posts: 14,771
| Oh yeah, sorry about that >_< CStringEx is the typedef name for the actual class named CTmplStringBase: Code: typedef CTmplStringBase< char, StrTraits<char> > CStringExA; typedef CTmplStringBase< wchar_t, StrTraits<wchar_t> > CStringExW; typedef CTmplStringBase< TCHAR, StrTraits<TCHAR> > CStringEx; Code: # define CTmplStringBaseTmpl Strings::CTmplStringBase<T, Traits> # define CTmplStringBaseTemplate template<typename T, typename Traits>
__________________ Using: Microsoft Windows™ 7 Professional (x64), Microsoft Visual Studio™ 2008 Team System I dedicated my life to helping others. This is only a small sample of what they said: "Thanks Elysia. You're a programming master! How the hell do you know every thing?" Quoted... at least once. Quote:
| |
| Elysia is offline | |
| | #258 |
| Cat without Hat Join Date: Apr 2003
Posts: 8,492
| You do realize that CTmplStringBaseTemplate is not significantly shorter than template<typename T, typename Traits>, but several magnitudes less readable, right? This is indeed weird.
__________________ All the buzzt! CornedBee"There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code." - Flon's Law |
| CornedBee is offline | |
| | #259 | ||
| Mysterious C++ User Join Date: Oct 2007
Posts: 14,771
| Quote:
But I also tried this. "The simplest possible snippet of code that compiles". Code: template<typename T> class CTest { public: CTest() {} CTest(const wchar_t*) {} };
template<typename T> void operator += (CTest<T>&, const CTest<T>&) {}
void Help()
{
CTest<wchar_t> a;
a += L"test";
} If I remove the template and explicitly specify wchar_t, it compiles. If I explicitly specify the constructor, such as a += CTest<wchar_t>(L"test"), it works too, but not with the templates.
__________________ Using: Microsoft Windows™ 7 Professional (x64), Microsoft Visual Studio™ 2008 Team System I dedicated my life to helping others. This is only a small sample of what they said: "Thanks Elysia. You're a programming master! How the hell do you know every thing?" Quoted... at least once. Quote:
| ||
| Elysia is offline | |
| | #260 |
| Cat without Hat Join Date: Apr 2003
Posts: 8,492
| Well, GCC agrees with VC++, even though it's even less informative. Simplest solution is apparently to just make += a member function. Or overload the free operator += for const wchar_t*.
__________________ All the buzzt! CornedBee"There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code." - Flon's Law |
| CornedBee is offline | |
| | #261 | |
| Mysterious C++ User Join Date: Oct 2007
Posts: 14,771
| Hm. Weird. Either a member or an overload for each of the types it can accept...
__________________ Using: Microsoft Windows™ 7 Professional (x64), Microsoft Visual Studio™ 2008 Team System I dedicated my life to helping others. This is only a small sample of what they said: "Thanks Elysia. You're a programming master! How the hell do you know every thing?" Quoted... at least once. Quote:
| |
| Elysia is offline | |
| | #262 | |||
| Registered User Join Date: Jan 2008
Posts: 627
| Quote:
Quote:
Quote:
Also, 'operator +=' should really be a method. Anyway, the reason this can't work: any specialization or even instantiation of 'CTmplStringBase' may have a constructor that takes a 'const wchar_t *' as an argument. How would the constructor choose between these instantiations? You have a few options (for this and the other operators): 1): Create a less ambiguous interface that forwards to the correct implementation--by explicitly instantiating the template function. 2): Create the function as a method, losing "left hand conversion". 3): Get partial "left hand" conversion by declaring the function as a friend and implementing it "inline"--not 'inline'. 4): My way, or less arrogantly: the way of the inspiring Andrei Alexandrescu. (Note: You lose implicit 'CTmplStringBase<X>' to 'CTmplStringBase<Y>' conversion, but this too can be overcome by adding in a little '1'.) Soma Code: template<typename T> class CTest { public: CTest() {} CTest(const wchar_t*) {} typedef CTest<T> this_type;};
template<typename T> void operator += (CTest<T>&, const typename CTest<T>::this_type &){}
void Help()
{
CTest<wchar_t> a;
a += L"test";
}
| |||
| phantomotap is offline | |
| | #263 | |
| Cat without Hat Join Date: Apr 2003
Posts: 8,492
| Quote:
__________________ All the buzzt! CornedBee"There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code." - Flon's Law | |
| CornedBee is offline | |
| | #264 | |
| Registered User Join Date: Jan 2008
Posts: 627
| Quote:
*shrug* Soma | |
| phantomotap is offline | |
| | #265 | |||||
| Mysterious C++ User Join Date: Oct 2007
Posts: 14,771
| Quote:
But I would assume the compiler should be able to guess, even in this instance. Quote:
Quote:
The way I see it: The compiler sees that it wants a class CTest of type X. Therefore the compiler looks at the class for CTest. It looks for a constructor to take one argument. It finds a constructor that takes const T*. Seeing as I add a wchar_t*, the compiler can easily deduce the type of T to wchar_t and call the constructor. The temporary object will then be of type CTest<wchar_t> and the compiler can deduce the type of T for the operator. But apparently my analogy is incorrect. Quote:
__________________ Using: Microsoft Windows™ 7 Professional (x64), Microsoft Visual Studio™ 2008 Team System I dedicated my life to helping others. This is only a small sample of what they said: "Thanks Elysia. You're a programming master! How the hell do you know every thing?" Quoted... at least once. Quote:
| |||||
| Elysia is offline | |
| | #266 | ||||||
| Registered User Join Date: Jan 2008
Posts: 627
| O_o Quote:
Quote:
Quote:
Quote:
Quote:
Quote:
For the foreseeable future, keep this thought in your head when programming with templates: only the instantiations of templates actually exist. Soma Last edited by phantomotap; 05-26-2008 at 04:02 AM. Reason: Elysia | ||||||
| phantomotap is offline | |
| | #267 | ||
| Mysterious C++ User Join Date: Oct 2007
Posts: 14,771
| Quote:
But I guess we don't have that luxury.
__________________ Using: Microsoft Windows™ 7 Professional (x64), Microsoft Visual Studio™ 2008 Team System I dedicated my life to helping others. This is only a small sample of what they said: "Thanks Elysia. You're a programming master! How the hell do you know every thing?" Quoted... at least once. Quote:
| ||
| Elysia is offline | |
| | #268 | |
| Registered User Join Date: Jan 2008
Posts: 627
| Quote:
You expect a compiler to examine a class that does not yet even potentially exist? (Edit: Yes CornedBee, that was derisive.) And anyway, that still doesn't answer the crucial question: where does the compiler start its examination? If you were to call every 'CTest<?>' by the name 'CTest', how would the compiler determine if any 'CTest' had a constructor taking a 'const wchar_t *'? (Remember, you just named the template argument relevant 'CTest<wchar_t>' constructor as taking a 'const self::arguments::_1 *' which may or may not be the same as 'const wchar_t *'.) If you look at every 'CTest<?>' by the name 'CTest', and a construct taking a 'const wchar_t *' is found, how do you determine the template arguments over any other valid arguments? (That is, how would you determine the types to pass to the parameters of the template if a partial specialization exists that has a constructor taking a 'const wchar_t *' regardless of the types the template is instantiated with?) By the by, this is also why you need 'template<typename T> void operator += (const typename CTest<T>::this_type &, CTest<T>&);'. Even with the existence of the companion operator the compiler can't know where to being, so it doesn't try. Soma Last edited by phantomotap; 05-26-2008 at 05:28 AM. | |
| phantomotap is offline | |
| | #269 | |||||
| Mysterious C++ User Join Date: Oct 2007
Posts: 14,771
| Quote:
So even if we append template before the class, it should be considered as a valid definition. The class CTest would exist, but not CTest<?> (no CTest<int>, no CTest<float>). Basically, no fully qualified class (full class type) would exist, but the general declaration of the template class, named CTest does exist. Quote:
If one or more specializations of the class does not exist in that header, then it's a programmer error, because this is just how normal classes works, as well. A full definition, including potential specializations. Then the compiler would be able to find the definition it seeks. Quote:
Let's look at a source: Code: template<typename T> class CTest { CTest(const T*) {} };
If it finds one, then it could try to match the argument I pass against T and see if it can generate an implicit conversion to const T*: Code: template<typename T> class CTest { CTest(const T*) {} };
int main()
{
CTest test("my test");
}
Then it can translate T = char* (because it's the argument we pass), so the constructor becomes: CTest(const char*) Then it will see if it can implicitly convert the argument we pass to that type. If it is successful, it calls the constructor and everyone is happy. But if it cannot match the type, then it must complain it cannot deduce T. If it finds several functions that may match, then it must complain ambiguous. Quote:
__________________ Using: Microsoft Windows™ 7 Professional (x64), Microsoft Visual Studio™ 2008 Team System I dedicated my life to helping others. This is only a small sample of what they said: "Thanks Elysia. You're a programming master! How the hell do you know every thing?" Quoted... at least once. Quote:
| |||||
| Elysia is offline | |
| | #270 | |||||||||||
| Registered User Join Date: Jan 2008
Posts: 627
| Quote:
Quote:
Quote:
Quote:
Quote:
Quote:
Quote:
Quote:
Quote:
Code: template <typename T> class CTest {CTest(const T*){} typedef T type;};
template <typename T> class CTest<type_vector<T, T>> {CTest(const char *){} typedef type_vector<T, T> type;};
int main()
{
CTest test("my test");
}
Which instantiation is more appropriate? Why? What would 'type' be a typedef for? And in the other case? Code: template <typename T> class CTest {CTest(){} typedef T type;}; // Note: Constructor
template <typename T> class CTest<type_vector<T, T>> {CTest(const char *){} typedef type_vector<T, T> type;};
int main()
{
CTest test("my test");
}
Quote:
Quote:
Soma | |||||||||||
| phantomotap is offline | |
![]() |
| Thread Tools | |
| Display Modes | |
|
Similar Threads | ||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| WS_POPUP, continuation of old problem | blurrymadness | Windows Programming | 1 | 04-20-2007 06:54 PM |
| Laptop Problem | Boomba | Tech Board | 1 | 03-07-2006 06:24 PM |
| implementation file | bejiz | C++ Programming | 5 | 11-28-2005 01:59 AM |
| Sorting problem.. well actually more of a string problem | fatdunky | C Programming | 5 | 11-07-2005 11:34 PM |
| Memory Problem - I think... | Unregistered | C Programming | 4 | 10-24-2001 12:14 PM |