Перейти к содержимому

No adl load xyz что за ошибка

  • автор:

Ошибка «No AMD graphics driver is installed, or the amd driver is not function»: как исправить

При попытке получить доступ к фирменному программному обеспечению AMD, например Radeon Settings или Radeon Catalyst, владельцы соответствующих видеокарт сталкиваются с ошибкой «No AMD graphics driver is installed, or the amd driver is not function». Помимо прочего, данная ошибка может возникать и после установки графического драйвера как самим пользователем, так и действиями Центра обновления. В сегодняшней статье мы разберем с вами, почему возникает эта проблема и как от нее избавиться.

No AMD graphics driver is installed, or the amd driver is not function

Причина ошибки «No AMD graphics driver is installed, or the amd driver is not function»

Из перевода этой ошибки можно узнать следующую информацию:

Драйвер для видеокарты AMD не установлен, или драйвер AMD не работает

Сразу же можно отметить наиболее правдоподобную причину: драйвер для графического ускорителя AMD, установленного в ПК пользователя, начал работать некорректно, что и привело к появлению ошибки. Собственно, искать дополнительных причин и не требуется, так как проблема определенно связана с драйвером для видеокарты от AMD.

Решение ошибки «No AMD graphics driver is installed, or the amd driver is not function»

Очевидно, что драйвер для видеокарты AMD начал работать некорректно, а поэтому нужно выполнить его переустановку. Чтобы добиться наилучшего результата, мы рекомендуем вам воспользоваться утилитой Display Driver Uninstaller, чтобы полностью удалить драйвер и прочее ПО для вашей видеокарты со своего компьютера. Загрузить последнюю версию этой программы вы можете по этой ссылке. Использовать Display Driver Uninstaller крайне просто, так что у вас не должно возникнуть никаких проблем.

Заметка: во время удаления графического драйвера программой Display Driver Uninstaller вам потребуется перезагружать свой компьютер, так что не забудьте завершить все важные дела перед ее использованием.

Запустите Display Driver Uninstaller, после чего перед вами появится следующее окошко:

Все, что вам нужно сделать — это выбрать производителя своего графического чипа и нажать на кнопку «УДАЛИТЬ И ПЕРЕЗАГРУЗИТЬ(настоятельно рекомендуется)». Как только с вашего компьютера будет полностью удален драйвер AMD, операционная система переключится на использование стандартного графического драйвера от Microsoft, что позволит вам пройти по следующей ссылке на официальный сайт AMD и загрузить последнюю версию драйвера к себе на ПК, а затем, понятное дело, установить. Также убедитесь, что с вашего ПК было удалено все фирменное ПО от AMD, а если нет — избавьтесь от него. После таких действий ошибка «No AMD graphics driver is installed, or the amd driver is not function» определенно будет устранена.

Однако, некоторым пользователям не удается избавиться от нее даже после полного удаления драйвера AMD из системы. Что же, порой, это действительно может произойти и виной тому могут послужить установочные файлы драйверов и ПО от AMD, которые все еще находятся на компьютере. Пройдите на ваш системный раздел, найдите на нем папку под названием AMD и полностью ее очистите. Как только сделаете это, снова повторите процесс с программой Display Driver Uninstaller и установкой драйвера для видеокарты с официального сайта. На этот раз ошибка «No AMD graphics driver is installed, or the amd driver is not function» практически стопроцентно будет решена.

Исправить ошибку No AMD graphics driver is installed

GRAVITSAPA.info - интересный блог

При обновлении или установке драйвера для видеокарты AMD получаем ошибку:

Проблема распространена в основном на ноутбуках HP, но может возникать и на других производителях, а так же на ПК.
Есть проверенный вариант устранения данной ошибки.

Удалить графический драйвер в режиме безопасности

  1. Запускаем Windows в режиме безопасности (в основном во время загрузки достаточно нажать F8, после чего выбрать в списке “Безопасный режим”)
  2. Заходим в Диспетчер устройств (нажимаем правой кнопкой мыши на “Мой компьютер”, выбираем “Управление”, в открывшемся окне слева выбираем “Диспетчер устройств”)
  3. Выбираем устройство “AMD Radeon…” (будет указана модель Вашей видеокарты), нажимаем правой кнопкой и выбираем “Свойство”, в открывшемся окне выбираем вкладку “Драйвер” в которой нажимаем кнопку “Удалить”
  4. Затем появится маленькое окошко подтверждения удаления драйвера, в нём нужно поставить отметку “Удалить программы драйверов для этого устройства”
  5. Закрываем окна, перезагружаем компьютер. Если на компьютере стоит Windows 10, то драйвера установятся автоматически (в течении часа). Если другая Windows, то зайдите на сайт производителя ноутбука или видеокарты (в случае если стационарный ПК) и скачайте актуальные драйвера.

Примечание: Ни в коем случае не качайте драйвера со сторонних сайтов!

Ещё статьи по теме:

  • Находим и запускаем Internet Explorer в Windows 10
  • Включаем отображение скрытых файлов и папок в Windows 7, 8, 10 и других
  • Включаем/отключаем отображение расширения файла в конце имени
  • Устранить ошибку: “На компьютере не достаточно памяти”
  • Как выбрать редакцию Windows 10 Pro во время чистой установки?

A template is a cookie-cutter that specifies how to cut cookies that all look pretty much the same (although the cookies can be made of various kinds of dough, they’ll all have the same basic shape). In the same way, a class template is a cookie cutter for a description of how to build a family of classes that all look basically the same, and a function template describes how to build a family of similar looking functions.

Class templates are often used to build type safe containers (although this only scratches the surface for how they can be used).

What’s the syntax / semantics for a “class template”?

Consider a container class Array that acts like an array of integers:

// This would go into a header file such as "Array.h" class Array < public: Array(int len=10) : len_(len), data_(new int[len]) < >~Array() < delete[] data_; >int len() const < return len_; >const int& operator[](int i) const < return data_[check(i)]; >// Subscript operators often come in pairs int& operator[](int i) < return data_[check(i)]; >// Subscript operators often come in pairs Array(const Array&); Array& operator= (const Array&); private: int len_; int* data_; int check(int i) const < if (i < 0 || i >= len_) throw BoundsViol("Array", i, len_); return i; > >; 

Repeating the above over and over for Array of float , of char , of std::string , of Array-of- std::string , etc, would become tedious. Instead, you add the template before the class definition (the T can be any identifier you want, T is just the most commonly used one, especially in examples). Then, instead of using int or float or char where referring to the data type, you use T instead. Also, instead of just referring to the class as Array, it’s Array when referring to the template, or Array , Array , etc. when referring to a specific instantiation.

// This would go into a header file such as "Array.h" template class Array < public: Array(int len=10) : len_(len), data_(new T[len]) < >~Array() < delete[] data_; >int len() const < return len_; >const T& operator[](int i) const < return data_[check(i)]; >T& operator[](int i) < return data_[check(i)]; >Array(const Array&); Array(Array&&); Array& operator= (const Array&); Array& operator= (Array&&); private: int len_; T* data_; int check(int i) const < assert(i >= 0 && i < len_); return i; >>; 

Just as with a normal class, you can optionally define your methods outside the class:

template class Array < public: int len() const; // . >; template inline // See below if you want to make this non-inline int Array::len() const < // . >

Unlike template functions, template classes (instantiations of class templates) need to be explicit about the parameters over which they are instantiating:

int main() < Arrayai; Array af; Array ac; Array as; Array aai; // . > 

Note that prior to C++11, a space was required between the two > ’s in the last example. Without this space, the C++98/C++03 compiler would see a >> (right-shift) token instead of two > ’s. Aren’t you lucky that it is no longer the case in C++11?

What’s the syntax / semantics for a “function template”?

Consider this function that swaps its two integer arguments:

void swap(int& x, int& y)

If we also had to swap floats, longs, Strings, Sets, and FileSystems, we’d get pretty tired of coding lines that look almost identical except for the type. Mindless repetition is an ideal job for a computer, hence a function template:

template void swap(T& x, T& y)

Every time we used swap() with a given pair of types, the compiler will go to the above definition and will create yet another “template function” as an instantiation of the above. Unlike template classes, template functions usually do not need to be explicit about the parameters over which they are instantiating. The compiler can usually determine them automatically. E.g.,

int main() < int i,j; /*. */ swap(i,j); // Instantiates a swap for int float a,b; /*. */ swap(a,b); // Instantiates a swap for float char c,d; /*. */ swap(c,d); // Instantiates a swap for char std::string s,t; /*. */ swap(s,t); // Instantiates a swap for std::string // . >

Note: A “template function” is the instantiation of a “function template”.

How do I explicitly select which version of a function template should get called?

When you call a function template, the compiler tries to deduce the template type. Most of the time it can do that successfully, but every once in a while you may want to help the compiler deduce the right type — either because it cannot deduce the type at all, or perhaps because it would deduce the wrong type.

For example, you might be calling a function template that doesn’t have any parameters of its template argument types, or you might want to force the compiler to do certain promotions on the arguments before selecting the correct function template. In these cases you’ll need to explicitly tell the compiler which instantiation of the function template should be called.

Here is a sample function template where the template parameter T does not appear in the function’s parameter list. In this case the compiler cannot deduce the template parameter types when the function is called.

template void f() < // . >

To call this function with T being an int or a std::string , you could say:

#include void sample() < f(); // type T will be int in this call f(); // type T will be std::string in this call > 

Here is another function whose template parameters appear in the function’s list of formal parameters (that is, the compiler can deduce the template type from the actual arguments):

template void g(T x) < // . >

Now if you want to force the actual arguments to be promoted before the compiler deduces the template type, you can use the above technique. E.g., if you simply called g(42) you would get g(42) , but if you wanted to pass 42 to g() , you could say this: g(42) . (Of course you could also promote the parameter explicitly, such as either g(long(42)) or even g(42L) , but that ruins the example.)

Similarly if you said g(«xyz») you’d end up calling g(char*) , but if you wanted to call the std::string version of g<>() you could say g(«xyz») . (Again you could also promote the argument, such as g(std::string(«xyz»)) , but that’s another story.)

Another time when you must specify the types is when the function takes two parameters of the same type, but you give it two different types.

template void g(T x, T y); int m = 0; long n = 1; g(m, n); 

Since m and n have different types, the compiler can’t deduce what type to use for T , so you have to tell it what to use:

template void g(T x, T y); int m = 0; long n = 1; g(m, n); 

What is a “parameterized type”?

Another way to say, “class templates.”

A parameterized type is a type that is parameterized over another type or some value. List is a type ( List ) parameterized over another type ( int ).

What is “genericity”?

Yet another way to say, “class templates.”

Not to be confused with “generality” (which just means avoiding solutions which are overly specific), “genericity” means class templates.

My template function does something special when the template type T is int or std::string ; how do I write my template so it uses the special code when T is one of those specific types?

Before showing how to do this, let’s make sure you’re not shooting yourself in the foot. Does the function’s behavior appear different to your users? In other words, is the observable behavior different in some substantive way? If so, you’re probably shooting yourself in the foot and you will probably confuse your users — you’re probably better off using different functions with different names — don’t use templates, don’t use overloading. For example, if the code for int inserts something into a container and sorts the result, but the code for std::string removes something from a container and does not sort the result, those two functions ought not to be an overloaded pair — their observable behavior is different so they ought to have different names.

However if the function’s observable behavior is consistent for all the T types with the differences limited to implementation details, then you can proceed. Let’s proceed with an example of this (conceptual only; not C++):

template void foo(const T& x) < switch (typeof(T)) < // Conceptual only; not C++ case int: // . implementation details when T is int break; case std::string: // . implementation details when T is std::string break; default: // . implementation details when T is neither int nor std::string break; >> 

One way to implement the above is via template specialization. Instead of a switch -statement, you end up breaking up the code into separate functions. The first function is the default case — the code to be used when T is anything other than int or std::string :

template void foo(const T& x) < // . implementation details when T is neither int nor std::string >

Next are the two specializations, first for the int case…

template<> void foo(const int& x) < // . implementation details when T is int >

…and next for the std::string case…

template<> void foo(const std::string& x) < // . implementation details when T is std::string >

That’s it; you’re done. The compiler will automagically select the correct specialization when it sees which T you are using.

Huh? Can you provide an example of template specialization that doesn’t use foo and bar ?

One of several ways I personally use template specialization is for stringification. I usually use a template to stringify various objects of various types, but I often need to specialize the code for stringifying certain specific types. For instance, when stringifying bool s I prefer «true» and «false» over «1» and «0» so I use std::boolalpha when T is bool . Also I often prefer floating point output to contain all the digits (so I can see very small differences, etc.) so I use std::setprecision when T is a floating point type. The end result usually looks something like this:

#include #include #include #include #include template inline std::string stringify(const T& x) < std::ostringstream out; out template<> inline std::string stringify(const bool& x) < std::ostringstream out; out << std::boolalpha template<> inline std::string stringify(const double& x) < const int sigdigits = std::numeric_limits::digits10; // or perhaps std::numeric_limits::max_digits10 if that is available on your compiler std::ostringstream out; out << std::setprecision(sigdigits) template<> inline std::string stringify(const float& x) < const int sigdigits = std::numeric_limits::digits10; // or perhaps std::numeric_limits::max_digits10 if that is available on your compiler std::ostringstream out; out << std::setprecision(sigdigits) template<> inline std::string stringify(const long double& x) < const int sigdigits = std::numeric_limits::digits10; // or perhaps std::numeric_limits::max_digits10 if that is available on your compiler std::ostringstream out; out

Conceptually they all do the same thing: stringify the parameter. That means the observable behavior is consistent, therefore the specializations do not confuse callers. However the details for implementing that observable behavior is slightly different for bool and floating point types, so template specialization is a good approach.

But most of the code in my template function is the same; is there some way to get the benefits of template specialization without duplicating all that source code?

For example, suppose your template function has a bunch of common code along with a relatively small amount of T -specific code (conceptual only; not C++):

template void foo(const T& x) < // . common code that works for all T types . switch (typeof(T)) < // Conceptual only; not C++ case int: // . small amount of code used only when T is int . break; case std::string: // . small amount of code used only when T is std::string . break; default: // . small amount of code used when T is neither int nor std::string . break; >// . more common code that works for all T types . > 

If you blindly applied the advice from the FAQ on template specialization, you would end up duplicating all that code before and after the pseudo-switch statement. The way to get the best of both worlds — to get the benefits of T -specific pieces without duplicating the entire function, is to extract the pseudo-switch statement portion into a separate function foo_part() , and use template specialization on that separate function:

template inline void foo_part(const T& x) < // . small amount of code used when T is neither int nor std::string . >template<> inline void foo_part(const int& x) < // . small amount of code used only when T is int . >template<> inline void foo_part(const std::string& x) < // . small amount of code used only when T is std::string . >

The main foo() function would be a simple template — no specializations. Note that the pseudo-switch statement has been replaced by a call to foo_part() :

template void foo(const T& x) < // . common code that works for all T types . foo_part(x); // . more common code that works for all T types . >

As you can see, the body of foo() now doesn’t mention any particular T . It all gets figured out automatically. The compiler generates foo for you based on type T , and will generate the correctly typed foo_part function based on the actual compile-time known type of the x argument. Proper specializations of foo_part will be instantiated.

All those templates and template specializations must slow down my program, right?

This is a quality-of-implementation issue so your results may vary. However there is usually no slow-down at all. If anything, the templates might affect the speed of compilation slightly, but once the types are resolved by the compiler at compile-time, it will typically generate code that is just as fast as with non-template functions, including inline-expanding appropriate functions, etc.

So templates are overloading, right?

Function templates participate in name resolution for overloaded functions, but the rules are different. For a template to be considered in overload resolution, the type has to match exactly. If the types do not match exactly, the conversions are not considered and the template is simply dropped from the set of viable functions. That’s what is known as “SFINAE” — Substitution Failure Is Not An Error. Example:

#include #include template void foo(T* x) < std::cout (T*)\n"; > void foo(int x) < std::cout void foo(double x) < std::cout int main() < foo(42); // matches foo(int) exactly foo(42.0); // matches foo(double) exactly foo("abcdef"); // matches foo(T*) with T = char return 0; > 

In this example, foo cannot be considered for the first or the second call to foo in the body of main because neither 42 nor 42.0 gives the compiler any information to deduce T . The third call, however, includes foo with T = char and it wins.

Why can’t I separate the definition of my templates class from its declaration and put it inside a .cpp file?

If all you want to know is how to fix this situation, read the next two FAQs. But in order to understand why things are the way they are, first accept these facts:

  1. A template is not a class or a function. A template is a “pattern” that the compiler uses to generate a family of classes or functions.
  2. In order for the compiler to generate the code, it must see both the template definition (not just declaration) and the specific types/whatever used to “fill in” the template. For example, if you’re trying to use a Foo , the compiler must see both the Foo template and the fact that you’re trying to make a specific Foo .
  3. Your compiler probably doesn’t remember the details of one .cpp file while it is compiling another .cpp file. It could, but most do not and if you are reading this FAQ, it almost definitely does not. BTW this is called the “separate compilation model.”

Now based on those facts, here’s an example that shows why things are the way they are. Suppose you have a template Foo defined like this:

template class Foo < public: Foo(); void someMethod(T x); private: T x; >; 

Along with similar definitions for the member functions:

template Foo::Foo() < // . >template void Foo::someMethod(T x) < // . >

Now suppose you have some code in file Bar.cpp that uses Foo :

// Bar.cpp void blah_blah_blah() < // . Foof; f.someMethod(5); // . > 

Clearly somebody somewhere is going to have to use the “pattern” for the constructor definition and for the someMethod() definition and instantiate those when T is actually int . But if you had put the definition of the constructor and someMethod() into file Foo.cpp , the compiler would see the template code when it compiled Foo.cpp and it would see Foo when it compiled Bar.cpp , but there would never be a time when it saw both the template code and Foo . So by rule #2 above, it could never generate the code for Foo::someMethod() .

A note to the experts: I have obviously made several simplifications above. This was intentional so please don’t complain too loudly. If you know the difference between a .cpp file and a compilation unit, the difference between a class template and a template class, and the fact that templates really aren’t just glorified macros, then don’t complain: this particular question/answer wasn’t aimed at you to begin with. I simplified things so newbies would “get it,” even if doing so offends some experts.

Reminder: Read the next two FAQs for some solutions to this problem.

How can I avoid linker errors with my template functions?

This answer will be updated due to C++11 extern template . Watch this space for updates in the near future!!

Tell your C++ compiler which instantiations to make while it is compiling your template function’s .cpp file.

As an example, consider the header file foo.h which contains the following template function declaration:

// File "foo.h" template extern void foo(); 

Now suppose file foo.cpp actually defines that template function:

// File "foo.cpp" #include #include "foo.h" template void foo()

Suppose file main.cpp uses this template function by calling foo() :

// File "main.cpp" #include "foo.h" int main() < foo(); // . > 

If you compile and (try to) link these two .cpp files, most compilers will generate linker errors. There are two solutions for this. The first solution is to physically move the definition of the template function into the .h file, even if it is not an inline function. This solution may (or may not!) cause significant code bloat, meaning your executable size may increase dramatically (or, if your compiler is smart enough, may not; try it and see).

The other solution is to leave the definition of the template function in the .cpp file and simply add the line template void foo(); to that file:

// File "foo.cpp" #include #include "foo.h" template void foo() < std::cout template void foo(); 

If you can’t modify foo.cpp , simply create a new .cpp file such as foo-impl.cpp as follows:

// File "foo-impl.cpp" #include "foo.cpp" template void foo(); 

Notice that foo-impl.cpp #include s a .cpp file, not a .h file. If that’s confusing, click your heels twice, think of Kansas, and repeat after me, “I will do it anyway even though it’s confusing.” You can trust me on this one. But if you don’t trust me or are simply curious, the rationale is given earlier.

How does the C++ keyword export help with template linker errors?

This answer will be updated due to C++11 extern template . Watch this space for updates in the near future!!

The C++ keyword export was originally designed to eliminate the need to include a template definition (either by providing the definition in the header file or by including the implementation file). However, only a few compilers ever supported this capability, such as Comeau C++ and Sun Studio, and the general consensus was that it was not worth the trouble.

Because of that, in the C++11 standard, the export feature has been removed from the language. It remains a reserved word but it no longer has any meaning.

If you are working with a compiler that supports the export keyword, it will probably continue to support the keyword via some sort of compiler option or extension until its users migrate away from it. If you already have code that uses export , you can use a fairly simple discipline to allow your code to easily migrate if/when your compiler stops supporting it entirely. Just define your template header-files like this:

// File Foo.h #ifdef USE_EXPORT_KEYWORD export #endif template class Foo < // . >; #ifndef USE_EXPORT_KEYWORD #include "Foo.cpp" #endif 

And define your non-inline functions in a source-file like this:

// File Foo.cpp #ifdef USE_EXPORT_KEYWORD export #endif template . 

Then compile with -DUSE_EXPORT_KEYWORD , or whatever equivalent compiler option lets you set a preprocessor symbol like USE_COMPILER_KEYWORD , and if/when your compiler removes support for export , just remove that compiler option.

How can I avoid linker errors with my template classes?

This answer will be updated due to C++11 extern template . Watch this space for updates in the near future!!

Tell your C++ compiler which instantiations to make while it is compiling your template class’s .cpp file.

(If you’ve already read the previous FAQ, this answer is completely symmetric with that one, so you can probably skip this answer.)

As an example, consider the header file Foo.h which contains the following template class. Note that method Foo::f() is inline and methods Foo::g() and Foo::h() are not.

// File "Foo.h" template class Foo < public: void f(); void g(); void h(); >; template inline void Foo::f() < // . >

Now suppose file Foo.cpp actually defines the non- inline methods Foo::g() and Foo::h() :

// File "Foo.cpp" #include #include "Foo.h" template void Foo::g() < std::cout << "Foo::g()\n"; > template void Foo::h() < std::cout << "Foo::h()\n"; > 

Suppose file main.cpp uses this template class by creating a Foo and calling its methods:

// File "main.cpp" #include "Foo.h" int main() < Foox; x.f(); x.g(); x.h(); // . > 

If you compile and (try to) link these two .cpp files, most compilers will generate linker errors. There are two solutions for this. The first solution is to physically move the definition of the template functions into the .h file, even if they are not inline functions. This solution may (or may not!) cause significant code bloat, meaning your executable size may increase dramatically (or, if your compiler is smart enough, may not; try it and see).

The other solution is to leave the definition of the template function in the .cpp file and simply add the line template class Foo; to that file:

// File "Foo.cpp" #include #include "Foo.h" // . definition of Foo::f() is unchanged -- see above. // . definition of Foo::g() is unchanged -- see above. template class Foo; 

If you can’t modify Foo.cpp , simply create a new .cpp file such as Foo-impl.cpp as follows:

// File "Foo-impl.cpp" #include "Foo.cpp" template class Foo; 

Notice that Foo-impl.cpp #include s a .cpp file, not a .h file. If that’s confusing, click your heels twice, think of Kansas, and repeat after me, “I will do it anyway even though it’s confusing.” You can trust me on this one. But if you don’t trust me or are simply curious, the rationale is given earlier.

If you are using Comeau C++, you probably want to learn about the export keyword.

Why do I get linker errors when I use template friends?

Ah, the intricacies of template friends. Here’s an example of what people often want to do:

#include template class Foo < public: Foo(const T& value = T()); friend Foooperator+ (const Foo& lhs, const Foo& rhs); friend std::ostream& operator<< (std::ostream& o, const Foo& x); private: T value_; >; 

Naturally the template will need to actually be used somewhere:

int main() < Foolhs(1); Foo rhs(2); Foo result = lhs + rhs; std::cout 

And of course the various member and friend functions will need to be defined somewhere:

template Foo::Foo(const T& value = T()) : value_(value) < >template Foo operator+ (const Foo& lhs, const Foo& rhs) < return Foo(lhs.value_ + rhs.value_); > template std::ostream& operator<< (std::ostream& o, const Foo& x)

The snag happens when the compiler sees the friend lines way up in the class definition proper. At that moment it does not yet know the friend functions are themselves templates; it assumes they are non-templates like this:

Foo operator+ (const Foo& lhs, const Foo& rhs) < /*. */ >std::ostream& operator<< (std::ostream& o, const Foo& x) < /*. */ >

When you call the operator+ or operatornon-template functions, but the linker will give you an “undefined external” error because you never actually defined those non-template functions.

The solution is to convince the compiler while it is examining the class body proper that the operator+ and operatorabove the definition of template class Foo :

template class Foo; // pre-declare the template class itself template Foo operator+ (const Foo& lhs, const Foo& rhs); template std::ostream& operator<< (std::ostream& o, const Foo& x); 

Also you add <> in the friend lines, as shown:

#include template class Foo < public: Foo(const T& value = T()); friend Foooperator+ <> (const Foo& lhs, const Foo& rhs); friend std::ostream& operator (std::ostream& o, const Foo& x); private: T value_; >; 

After the compiler sees that magic stuff, it will be better informed about the friend functions. In particular, it will realize that the friend lines are referring to functions that are themselves templates. That eliminates the confusion.

Another approach is to define the friend function within the class body at the same moment you declare it to be a friend . For example:

#include template class Foo < public: Foo(const T& value = T()); friend Foooperator+ (const Foo& lhs, const Foo& rhs) < // . >friend std::ostream& operator<< (std::ostream& o, const Foo& x) < // . >private: T value_; >; 

Why can’t I define constraints for my template parameters?

(Note: This FAQ is a bit dated and needs to be updated for static_assert .)

Well, you can, and it’s quite easy and general.

 template void draw_all(Container& c)

If there is a type error, it will be in the resolution of the fairly complicated for_each() call. For example, if the element type of the container is an int , then we get some kind of obscure error related to the for_each() call (because we can’t invoke Shape::draw() for an int ).

To catch such errors early, you can write:

 template void draw_all(Container& c) < Shape* p = c.front(); // accept only containers of Shape*s for_each(c.begin(),c.end(),mem_fun(&Shape::draw)); >

The initialization of the spurious variable p will trigger a comprehensible error message from most current compilers. Tricks like this are common in all languages and have to be developed for all novel constructs. In production code, you’d probably write something like:

 template void draw_all(Container& c) < typedef typename Container::value_type T; Can_copy(); // accept containers of only Shape*s for_each(c.begin(),c.end(),mem_fun(&Shape::draw)); > 

This makes it clear that you’re making an assertion. The Can_copy template can be defined like this:

 template struct Can_copy < static void constraints(T1 a, T2 b) < T2 c = a; b = a; >Can_copy() < void(*p)(T1,T2) = constraints; >>; 

Can_copy checks (at compile time) that a T1 can be assigned to a T2 . Can_copy checks that T is a Shape* or a pointer to a class publicly derived from Shape or a type with a user-defined conversion to Shape* . Note that the definition is close to minimal:

  • one line to name the constraints to be checked and the types for which to check them
  • one line to list the specific constraints checked (the constraints() function)
  • one line to provide a way to trigger the check (the constructor)

Note also that the definition has the desirable properties that

  • You can express constraints without declaring or copying variables, thus the writer of a constraint doesn’t have to make assumptions about how a type is initialized, whether objects can be copied, destroyed, etc. (unless, of course, those are the properties being tested by the constraint)
  • No code is generated for a constraint using current compilers
  • No macros are needed to define or use constraints

Current compilers give acceptable error messages for a failed constraint, including the word “constraints” (to give the reader a clue), the name of the constraints, and the specific error that caused the failure (e.g. “cannot initialize Shape* by double* ”)

So why is something like Can_copy() – or something even more elegant – not in the language? A way to specify these constraints directly is being worked on as we speak – see Concepts Lite.

Until then, the above the idea is very general. After all, when we write a template we have the full expressive power of C++ available. Consider:

 template struct Derived_from < static void constraints(T* p) < B* pb = p; >Derived_from() < void(*p)(T*) = constraints; >>; template struct Can_copy < static void constraints(T1 a, T2 b) < T2 c = a; b = a; >Can_copy() < void(*p)(T1,T2) = constraints; >>; template struct Can_compare < static void constraints(T1 a, T2 b) < a==b; a!=b; aCan_compare() < void(*p)(T1,T2) = constraints; >>; template struct Can_multiply < static void constraints(T1 a, T2 b, T3 c) < c = a*b; >Can_multiply() < void(*p)(T1,T2,T3) = constraints; >>; struct B < >; struct D : B < >; struct DD : D < >; struct X < >; int main() < Derived_from(); Derived_from(); Derived_from(); Derived_from(); Derived_from(); Can_compare(); Can_compare(); Can_multiply(); Can_multiply(); Can_multiply(); Can_copy(); Can_copy(); Can_copy(); > // the classical "elements must derived from Mybase*" constraint: template class Container : Derived_from < // . >; 

Actually, Derived_from doesn’t check derivation, but conversion, but that’s often a better constraint. Finding good names for constraints can be hard.

How can any human hope to understand these overly verbose template-based error messages?

Compiler error messages have got much better in recent years, and show human-readable typedefs, as well as highlighting where in the source-code the error occurred.

If you’re still using an older compiler, here’s a free tool that transforms error messages into something more understandable. The tool is no longer being developed, but worked with the following compilers: Comeau C++, Intel C++, CodeWarrior C++, GCC, Borland C++, Microsoft Visual C++, and EDG C++.

Here’s an example showing some unfiltered GCC error messages:

rtmap.cpp: In function `int main()': rtmap.cpp:19: invalid conversion from `int' to ` std::_Rb_tree_node >*' rtmap.cpp:19: initializing argument 1 of `std::_Rb_tree_iterator::_Rb_tree_iterator(std::_Rb_tree_node*) [with _Val = std::pair, _Ref = std::pair&, _Ptr = std::pair*]' rtmap.cpp:20: invalid conversion from `int' to ` std::_Rb_tree_node >*' rtmap.cpp:20: initializing argument 1 of `std::_Rb_tree_iterator::_Rb_tree_iterator(std::_Rb_tree_node*) [with _Val = std::pair, _Ref = std::pair&, _Ptr = std::pair*]' E:/GCC3/include/c++/3.2/bits/stl_tree.h: In member function `void std::_Rb_tree::insert_unique(_II, _II) [with _InputIterator = int, _Key = int, _Val = std::pair, _KeyOfValue = std::_Select1st >, _Compare = std::less, _Alloc = std::allocator >]': E:/GCC3/include/c++/3.2/bits/stl_map.h:272: instantiated from `void std::map::insert(_InputIterator, _InputIterator) [with _Input Iterator = int, _Key = int, _Tp = double, _Compare = std::less, _Alloc = st d::allocator >]' rtmap.cpp:21: instantiated from here E:/GCC3/include/c++/3.2/bits/stl_tree.h:1161: invalid type argument of `unary * ' 

Here’s what the filtered error messages look like (note: you can configure the tool so it shows more information; this output was generated with settings to strip things down to a minimum):

rtmap.cpp: In function `int main()': rtmap.cpp:19: invalid conversion from `int' to `iter' rtmap.cpp:19: initializing argument 1 of `iter(iter)' rtmap.cpp:20: invalid conversion from `int' to `iter' rtmap.cpp:20: initializing argument 1 of `iter(iter)' stl_tree.h: In member function `void map::insert_unique(_II, _II)': [STL Decryptor: Suppressed 1 more STL standard header message] rtmap.cpp:21: instantiated from here stl_tree.h:1161: invalid type argument of `unary *' 

Here is the source code to generate the above example:

#include #include #include const int values[] = < 1,2,3,4,5 >; const int NVALS = sizeof values / sizeof (int); int main() < using namespace std; typedef mapvalmap; valmap m; for (int i = 0; i < NVALS; i++) m.insert(make_pair(values[i], pow(values[i], .5))); valmap::iterator it = 100; // error valmap::iterator it2(100); // error m.insert(1,2); // error return 0; >

Why am I getting errors when my template uses a nested type?

Perhaps surprisingly, the following code is not valid C++, even though some compilers accept it:

template bool contains(const Container& c, const T& val) < Container::iterator iter; // Error, "Container::iterator" is not a type iter = std::find(c.begin(), c.end(), val); return iter !=- c.end(); >

The reason is that in theory the function template could be called with a type that has a data member or a member function called iterator . When the compiler is parsing the template contains it doesn’t know anything about the types it will be passed by the code that comes later. This means that until the compiler knows what Container is and what members it has, there’s no way to know whether Container::iterator is a type or not. In fact, the rules of C++ say that until told otherwise, the compiler must assume Container::iterator is not a type. The solution is to give the compiler a hint via the typename keyword:

template bool contains(const Container& c, const T& val)

This tells the compiler that when the function template is used later its argument will always be something for which Container::iterator is a type. (And if you actually try to call it with a type where iterator is a data member or something else, you will get an error).

Why am I getting errors when my template-derived-class uses a nested type it inherits from its template-base-class?

Perhaps surprisingly, the following code is not valid C++, even though some compilers accept it:

template class B < public: class Xyz < /*. */ >; // Type nested in class B typedef int Pqr; // Type nested in class B >; template class D : public B  < public: void g() < Xyz x; // Bad (even though some compilers erroneously (temporarily?) accept it) Pqr y; // Bad (even though some compilers erroneously (temporarily?) accept it) >>; 

This might hurt your head; better if you sit down.

Within D::g() , name Xyz and Pqr do not depend on template parameter T , so they are known as a nondependent names. On the other hand, B is dependent on template parameter T so B is called a dependent name.

Here’s the rule: the compiler does not look in dependent base classes (like B ) when looking up nondependent names (like Xyz or Pqr ). As a result, the compiler does not know they even exist let alone are types.

At this point, programmers sometimes prefix them with B:: , such as:

template class D : public B < public: void g() < B::Xyz x; // Bad (even though some compilers erroneously (temporarily?) accept it) B::Pqr y; // Bad (even though some compilers erroneously (temporarily?) accept it) > >; 

Unfortunately this doesn’t work either because those names (are you ready? are you sitting down?) are not necessarily types. “Huh. ” you say. “Not types. ” you exclaim. “That’s crazy; any fool can SEE they are types; just look. ” you protest. Sorry, the fact is that they might not be types. The reason is that there can be a specialization of B , say B , where B::Xyz is a data member, for example. Because of this potential specialization, the compiler cannot assume that B::Xyz is a type until it knows T . The solution is to give the compiler a hint via the typename keyword:

template class D : public B < public: void g() < typename B::Xyz x; // Good typename B::Pqr y; // Good > >; 

Why am I getting errors when my template-derived-class uses a member it inherits from its template-base-class?

Perhaps surprisingly, the following code is not valid C++, even though some compilers accept it:

template class B < public: void f() < >// Member of class B >; template class D : public B  < public: void g() < f(); // Bad (even though some compilers erroneously (temporarily?) accept it) >>; 

This might hurt your head; better if you sit down.

Within D::g() , the name f does not depend on template parameter T , so f is known as a nondependent name. On the other hand, B is dependent on template parameter T so B is called a dependent name.

Here’s the rule: the compiler does not look in dependent base classes (like B ) when looking up nondependent names (like f ).

This doesn’t mean that inheritance doesn’t work. Class D is still derived from class B , the compiler still lets you implicitly do the is-a conversions (e.g., D* to B* ), dynamic binding still works when virtual functions are invoked, etc. But there is an issue about how names are looked up.

  • Change the call from f() to this->f() . Since this is always implicitly dependent in a template, this->f is dependent and the lookup is therefore deferred until the template is actually instantiated, at which point all base classes are considered.
  • Insert using B::f; just prior to calling f() .
  • Change the call from f() to B::f() . Note however that this might not give you what you want if f() is virtual, since it inhibits the virtual dispatch mechanism.

Can the previous problem hurt me silently? Is it possible that the compiler will silently generate the wrong code?

Since non-dependent types and non-dependent members are not found in the dependent template base-classes, the compiler will search the enclosing scope, such as the enclosing namespace. This can cause it to silently(!) do the wrong thing.

class Xyz < /*. */ >; // Global ("namespace scope") type void f() < >// Global ("namespace scope") function template class B < public: class Xyz < /*. */ >; // Type nested in class B void f() < >// Member of class B >; template class D : public B  < public: void g() < Xyz x; // Suprise: you get the global Xyz!! f(); // Suprise: you get the global f!! >>; 

The use of Xyz and f within D::g() will silently(!) resolve to the global entities rather than those inherited from class B .

You have been warned.

How can I create a container-template that allows my users to supply the type of the underlying container that actually stores the values?

First, let’s clarify the question: the goal is to create a template Foo<> , but having the template parameter-list include some particular type of std::vector or std::list or some other (possibly non-standard) container to actually store the values.

Here’s one way to do that:

template class Foo < public: // typename value_type is the type of the values within a Foo-container typedef typename Underlying::value_type value_type; void insert(const typename value_type& x) < // . code to insert x into data_. >// . private: Underlying data_; >; Foo > x; Foo > y; 

If you want to allow your users to provide you with an underlying container that does not necessarily have a value_type typedef (such as some container from a third party), you could provide the value-type explicitly:

template class Foo < public: // typename value_type is the type of the values within a Foo-container typedef T value_type; void insert(const typename value_type& x) < // . code to insert x into data_. >// . private: Underlying data_; >; Foo > x; Foo > y; 

However you cannot (yet) provide an unspecified template as a template parameter, such as this:

template class Underlying> // Conceptual only; not C++ class Foo < public: // . private: Underlyingdata_; // Conceptual only; not C++ >; Foo x; // Conceptual only; not C++ Foo y; // Conceptual only; not C++ 

Follow-up to previous: can I pass in the underlying structure and the element-type separately?

Yes, with a “proxy” trick.

Here’s the problem: std::vector template can have, does have, more than one argument. You’re required to make them match in the number, order, and nature — type/non-type, etc.

It is possible, however, to “cheat” your way out of specifying all those arguments and use the defaults. It’s called the “proxy template” technique:

#include #include template struct wrap_vector < typedef std::vectortype; >; template struct wrap_list < typedef std::listtype; >; template class C> struct A < typename C::type data; // trick to use a proxy >; int main() < Aavi; A adl; // . > 

You can also create a proxy if you actually have a template that takes only one argument:

template struct wrap_my1argtemplate < typedef my1argtemplatetype; >; 

The “template typedefs” proposal will allow redefining templates just like we do with types, which will make the proxy-trick unnecessary. Until then, use something like the above.

Related: all those proxies must negatively reflect on the speed of my program. Don’t they?

They might require an extra microsecond to compile, but once all the types are resolved by the compiler, the resulting code is just as fast as if you used them directly without any proxy templates whatsoever.

Not only that, there are some techniques (template meta programming or TMP) that can, under the right circumstances, improve the efficiency of the generated code. The basic notion is to get the compiler to do more work at compile-time so less work has to be done at runtime.

Please Login to submit a recommendation.

If you don’t have an account, you can register for free.

Inside 3ds Max 4

This latest edition of Inside 3ds max is retooled to focus on the needs of the intermediate to professional user, based on continuing conversations with our target audience. This market is crying out for information that goes beyond the basic to provide guidance on how to make the most use of the program in real-world work situations. Inside 3ds Max 4 explores changes in the program as well as more advanced functionalities and how they can assist the professional user in enhancing efficiency or output. Inside 3ds max 4 is organized into units that mirror and actually step through the workflow of a 3D project. Moreover, where differences exist in the application of techniques between the broadcast/film and game/interactive applications, the authors present careful analysis to assist readers in making the right choices for their technical work. The CD-ROM includes all of the project files necessary to complete the projects as well as any plug-ins referred to in the text.

Избранные страницы

Содержание

Changes in Modeling and Materials
Changes in Animation
Changes in Rendering
Production Workflow
Workflow in the GamesInteractive Environment
NonOrganic Modeling for GamesInteractive Applications
MaterialsShadersMapping for the Jester
MaterialsShaders and Mapping for GamesInteractive
Building SubObject Materials
Animation Techniques
Particle Effects
Scripting Custom Animations
OrganicCharacter Modeling Using the Patch Method
OrganicCharacter Modeling Using the Box Method
OrganicCharacter Modeling for GamesInteractive
OrganicCharacter Model Rigging for BroadcastFilm
OrganicCharacter Model Rigging for GamesInteractive
Materials and Mapping
Lighting Techniques for GamesInteractive Applications
Rendering and Compositing
Compositing and Finishing in Combustion
Whats on the CDROM

Часто встречающиеся слова и выражения

Популярные отрывки

Стр. 872 - SuccessLease and all IBM product names are registered trademarks or trademarks of International Business Machines Corporation. Intel, the Intel Inside logo and Pentium are registered trademarks and Celeron is a trademark of Intel Corporation Other company, product and service names may be trademarks or service marks of others ©2001 IBM Corp. All rights reserved. ‎

Ссылки на эту книгу

Essential CG Lighting Techniques
Darren Brooker
Просмотр фрагмента - 2003
Essential CG Lighting Techniques
Darren Brooker
Просмотр фрагмента - 2003

Об авторе (2002)

Kim Lee is a freelance animator/technical director based in New York City. A former senior animator at Curious Pictures, Kim has worked with many New York-based production houses, including Pitch Productions, Nick Digital, Spontaneous Combustion, and Shooting Gallery. He is also a freelance demo artist/trainer for Discreet, and is recognized as one of the top trainers for 3ds max and combustion. In his position as a leading Discreet Training Specialist, he has trained artists and instructors in both Europe and North America at companies as diverse as IBM, Electronic Arts, and MTV. He co-authored 3D Studio 2.5 Effects Magic (New Riders) and teaches part-time at the Pratt Institute's Continuing Education program. One of his passions is creating independent 3D shorts such as "Pool Tools," produced with Boris Ustaev, which was the demo reel signature piece for Discreet's booth at SIGGRAPH '99. He also owns Worlds Away Productions, a small boutique production company focused on broadcast and 3D Web content.Brian Austin is co-founder, along with Boris Ustaev, of orisian, a production/funding studio based in New York City. Formerly an animator at Spontaneous Combustion, a New York-based digital studio specializing in creating visual effects and design for the advertising, broadcast, and film industries, Brian's animation talents have earned him a Grammy nomination, plus two Telly Awards. His icon/interface design can be found on Reuters risk management software. Before turning to the commercial world, Brian worked as a fine artist; he has been in many shows, including, most recently, PS1 Contemporary Arts Center (1999) and Exit Art (1997) in New York City. His artwork is in the collection of the Museum of Modern Art and C.W. Post College. In 1996, he developed and organized a group installation and public symposium at the Nexus Contemporary Art Center in Atlanta. He has created Off-Broadway theatre sets and exhibition design. Brian holds a Bachelor of Fine Arts in painting from the School of Visual Arts in New York, and studied architecture and animation at Pratt University, NYU, and Parsons School of Design.Doug Barnard is presently employed at Illusion Inc. as an art director, designing the next generation of virtual-reality entertainment. In the evenings, he teaches 3ds max 4 at the DH Institute of Media Arts in Santa Monica, California. He has been a freelance digital artist/consultant for clients such as Sony Music, MCA, the Disney Channel, Krislin Entertainment, and Activision. At the bleeding edge of technology, he is an alpha/beta tester for Discreet's 3ds max, character studio, and combustion. His published writing credits include chapters in Inside 3D Studio MAX 2, 3, and 4 and chapters in Discreet's courseware for 3ds max 3 and 4 and character studio 2 and 3. He spends his off-hours scheming on ways to build a boat and cruise off to be a digital artist in paradise.Neil Blevins has been an artist since approximately the age of three. However, he entered the 3D arena about six years ago using POVRRay, 3D Studio DOS, and finally max when it was first released. He is actively part of the 3D community, answering questions on the Discreet Web board (http://www.support.discreet.com), writing tutorials, and displaying art at his Web site (http://www.neilblevins.com). After graduating from Concordia University with a degree in Design Art, Neil started working at the all-powerful Blur Studio in Venice, California, making content for video games, film, and television (commercials and broadcast). He has recently expanded his areas of interest to include scripting. Visit http://www.blur.com/blurmaxscripts for close to 100 scripts available for free download.Ian Christie is currently a senior technical director at Industrial Light & Magic, the largest and oldest

Библиографические данные

Название Inside 3ds Max 4
Inside (New Riders)
Inside Series
Автор Kim Lee
Редактор Kim Lee
Издание: иллюстрированное
Издатель New Riders, 2002
ISBN 0735710945, 9780735710948
Количество страниц Всего страниц: 881
   
Экспорт цитаты BiBTeX EndNote RefMan

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *