Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ Function Template Questions

Tags:

c++

templates

I've been using C# so long, I have a couple of questions about function templates in C++.

template <typename T>
T max(T x, T y)
{
    return (x > y) ? x : y;
}
  1. Why do some examples use typename and other examples use class in the template parameter declaration? What is the difference?
  2. Is there any way to restrict T to a particular type, or to a type that derives from a particular type?
  3. Is there any way for a class to have two methods with the same name, except one is templated and the other is not?

UPDATE:

I appreciate all the answers, but several of them contain examples that I won't compile when I try to apply them to my code.

To clarify question 3, I have the following method:

template<typename T>
std::unique_ptr<T> ExecuteSqlQuery(LPCTSTR pszSqlQuery, UINT nOpenType = AFX_DB_USE_DEFAULT_TYPE);

I would like to declare a variation of this that uses CRecordset as T, so that either of the following statements would be valid:

auto result = db.ExecuteSqlQuery<CCustomerRecordset>(L"SELECT ...");

auto result = db.ExecuteSqlQuery(L"SELECT ...");
like image 364
Jonathan Wood Avatar asked Nov 29 '22 00:11

Jonathan Wood


2 Answers

Why do some examples use typename and other examples use class in the template parameter declaration? What is the difference?

There is no difference between the two in the template parameter declaration, however they both have additional separate meanings in other contexts. E.g. typename is used to mark dependent names as type names and class is used to introduce a class declaration.

Is there any way to restrict T to a particular type, or a type that derives from a particular type?

Yes, one way is to rely on SFINAE to discard instantiations of types satisfying some condition, often facilitated by std::enable_if, e.g. (using C++14):

template<typename T, typename = std::enable_if_t<std::is_base_of_v<SomeBaseClass, T>>
T max(T x, T y)
{
    return (x > y) ? x : y;
}

In the upcoming C++20, there will be support for Concepts, which allow one to write

template<std::DerivedFrom<SomeBaseClass> T>
T max(T x, T y)
{
    return (x > y) ? x : y;
}

Is there any way for a class to have two methods with the same name, except one is templated and the other is not?

Yes, this is possible. In overload resolution, if both candidates would be equally well matching, the non-templated one will be preferred.

like image 71
walnut Avatar answered Dec 09 '22 14:12

walnut


  1. In this particular context both class and typename mean exaclty the same, there is no difference. class is just a bit shorter :-).

  2. Until C++20 we could try and restrict template arguments using sophisticated template metaprogramming in conjunction with SFINAE technique. Basically, it makes template instantiation fail if the argument does not satisfy some condition. While it's very powerfull approach, it has its drawbacks: increased compile times and very long and unclear error messages.

    In C++20 we have a new language feature named concepts, which is aimed to do exactly the same in a simple and straightforward way.

  3. Yes, a function template can be overloaded with a regular function. If the both match, the regular function will be chosen. Note however that in general template overload resolution is quite complicated topic.

like image 20
Igor R. Avatar answered Dec 09 '22 16:12

Igor R.