Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does template<typename T, T> mean?

I was reading this prehistoric metaprogam example to detect whether a class supports member find. (or any other member).

template<typename T>
class DetectFind
{
    struct Fallback { int find; }; 
    struct Derived : T, Fallback { };

    template<typename U, U> struct Check;

    typedef char Yes[1];  
    typedef char No[2]; 

    template<typename U>
    static No& func(Check<int Fallback::*, &U::find>*);

    template<typename U>
    static Yes& func(...);

public:
    typedef DetectFind type;
    enum { value = sizeof(func<Derived>(0)) == sizeof(Yes) };
};

int main()
{
    std::cout << DetectFind<std::vector<int> >::value << std::endl;
    std::cout<< DetectFind<std::set<int> >::value << std::endl;
}

Intuitively I do understand the aim behind this, but if someone would ask me to write same thing from scratch after 10 days, I maybe will fail this.
The reason for that is that I do not fully understand the syntactical and language stretch that is used here.
Can someone please explain what the following syntaxes mean?

  1. Check<int Fallback::*, &U::find>* (I know its trying to benefit from SFIANE here, but how is this detecting the existence of find, I beleive this is linked to the second question as well)
  2. template<typename U, U> struct Check;

The program outputs 0 1 as predicted;

like image 851
Eduard Rostomyan Avatar asked Aug 31 '21 09:08

Eduard Rostomyan


People also ask

What is the difference between template typename T and template T?

There is no difference. typename and class are interchangeable in the declaration of a type template parameter.

What is typename in template?

" typename " is a keyword in the C++ programming language used when writing templates. It is used for specifying that a dependent name in a template definition or declaration is a type.

Is typename and class the same?

There is no difference between using <typename T> OR <class T> ; i.e. it is a convention used by C++ programmers.

What is meant by template parameter?

A template parameter is a special kind of parameter that can be used to pass a type as argument: just like regular function parameters can be used to pass values to a function, template parameters allow to pass also types to a function.

What are template and typename keywords in C++?

The template and typename keywords are routinely used to define templates. This is not the topic of this page as we assume that the reader is aware of this (otherwise consult a C++ book). The following example should illustrate this use of the template keyword.

How does the compiler determine the type of a non-type template argument?

In Visual Studio 2017 and later, and in /std:c++17 mode or later, the compiler deduces the type of a non-type template argument that's declared with auto: A template can be a template parameter. In this example, MyClass2 has two template parameters: a typename parameter T and a template parameter Arr:

How do you define a template in C++?

The template and typename keywords are routinely used to define templates. This is not the topic of this page as we assume that the reader is aware of this (otherwise consult a C++ book). The following example should illustrate this use of the template keyword. template <typename T>. bool isPositive(T x)

What is a template in Python?

A template is a construct that generates an ordinary type or function at compile time based on arguments the user supplies for the template parameters. For example, you can define a function template like this:


Video Answer


3 Answers

template<typename U, U> means there are two template arguments: an arbitrary type U, and an unnamed non-type template argument (eg. a value argument) whose type is U. As an example, an int scenario would be ClassName<int,42>.

In your example, the type U is a pointer to int member, and the value is the address of an int member.

like image 122
WhozCraig Avatar answered Oct 26 '22 14:10

WhozCraig


First, let us consider the struct Derived. Since it derives from Fallback it certainly contains a int field find, and possibly a member function find, whose existence is what you want to check.

As noted in the answer above, in the declaration of the struct Check, the first template parameter is as type, and the second is a non-type parameter, of the type given by the first parameter.

Given that, let us examine the two overloads of func. The first overload takes a pointer to a Check struct, whose first template parameters is a type equal to pointer-to-int member of Fallback (int Fallback::*). The second template parameter is then interpreted as a pointer-to-int member with value is &U::find. Given U = Derived, if T contains a find member function, this second parameter of Check is ambiguous, as it could also refer to the int find inherited by Fallback. By SFINAE, this overload of func will be then discarded.

The second func overload is always well defined. But if the first overload is not discarded, the second one is less specialized, so the the compiler will choose the first overload.

In summary: if U in template <typename U> func contains a member function find, the compiler chooses the second overload of func. If the member function find is absent, the compiler chooses the first overload.

Finally, the value of DetectFind is determined by the size of the returning type of the chosen func, which depending on the overload is a char array of size 1 or 2. From there, you get which overload of func is chosen, and from the discussion above, whether T has a member function find or not.

like image 1
francesco Avatar answered Oct 26 '22 12:10

francesco


Let's firstly cover the declaration of struct Check; template<typename U,U> struct Check means a that template arguments are

  1. An ordinary type U
  2. An object of type U, which doesn't have name.

Check<int Fallback::*, &U::find>* is a little bit more confusing.

The first template argument is a pointer to member., in this case it stands for a pointer to an member of class Fallback of type int, which would have allowed us to write something like this.

Fallback obj{10};
int Fallback::* find_ptr = &Fallback::find;
std::cout << obj.*find << std::endl;   //prints 10, note: ".*" is a separate operator

The second argument of the template is the address of the member of class U, as the initial declaration of struct Check suggested.

like image 1
Karen Baghdasaryan Avatar answered Oct 26 '22 14:10

Karen Baghdasaryan