Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Better way to disable argument-based template parameter deduction for functions?

Tags:

c++

templates

Here is what I want to do:

template <typename T> void f(DisableDeduction<T> obj) {std::cout << obj;}
// Here DisableDeduction<T> aliases T, but in a such way
// that would prevent compiler from deducing T based
// on provided argument.

/* ... */

f<int>(1); // Works.
f(1); // Error, can't deduce template parameter based on argument.

This is how I currently achieve it:

template <typename T> struct DisableDeduction_Internal {using type = T;};
template <typename T> using DisableDeduction = typename DisableDeduction_Internal<T>::type;

It works perfectly (as described), but it introduces one extra helper type.

But can I achieve same result without extra types?

like image 514
HolyBlackCat Avatar asked Jun 09 '16 22:06

HolyBlackCat


People also ask

What is template argument deduction?

Template argument deduction is used when selecting user-defined conversion function template arguments. A is the type that is required as the result of the conversion. P is the return type of the conversion function template.

How will you restrict the template for a specific datatype?

There are ways to restrict the types you can use inside a template you write by using specific typedefs inside your template. This will ensure that the compilation of the template specialisation for a type that does not include that particular typedef will fail, so you can selectively support/not support certain types.

What is CTAD C++?

Class Template Argument Deduction (CTAD) is a C++17 Core Language feature that reduces code verbosity. C++17's Standard Library also supports CTAD, so after upgrading your toolset, you can take advantage of this new feature when using STL types like std::pair and std::vector.

Can we use non-type parameters as argument templates?

A non-type template argument provided within a template argument list is an expression whose value can be determined at compile time. Such arguments must be constant expressions, addresses of functions or objects with external linkage, or addresses of static class members.


1 Answers

You can do it by putting T in non deducible context (to the left of ::), and use std::common_type from <type_traits>.

example:

template <typename T> void f(typename std::common_type<T>::type obj) {std::cout << obj;}
like image 116
marcinj Avatar answered Sep 20 '22 19:09

marcinj