How to prevent implicit value-preserving conversion of a templated alias? - c++

I'd like to add compile-time checking for different meanings of double. In the real world, I'm trying to make sure all calculations are done in consistent units. For the purposes of this question, I've concocted a toy example in which numbers have flavors.
I've been trying to achieve this based on a template parameter. Using the c++0x aliases feature described in another answer, I declared a Number<Flavor> as:
enum Flavor { Cherry, Plum, Raspberry };
template <Flavor> using Number = double;
This gives me the ability to declare local variables or parameters as particular flavors of Number, then use those variables as ordinary doubles in most contexts.
My problem is, I can't find a way to declare a function that will only accept a particular flavor as its argument:
void printCherryNumber(Number<Cherry> num) { cout << num << endl; }
int main() {
Number<Cherry> a(5);
Number<Plum> b(6);
Number<Raspberry> c(3.1415);
printCherryNumber(a);
printCherryNumber(b); // O, if only this could be a compiler error.
return 0;
}
My goal is to make printCherryNumber(b) fail to compile because b is a Number<Plum> not Number<Cherry>. Many existing questions tackle variations on this problem with solutions that seem to not work on the type alias construct I've used for Number.
Stuff I've Tried
From this answer, I see the suggestion to add a templated version of the function that explicitly does nothing or breaks, as in
template <typename T> void printCherryNumber(T num) = delete;
This has no effect at all, and why should it? Number<Plum> is really double and Number<Cherry> is also double so the compiler never bothers with the templated version.
Another answer suggests using a single templated function and static asserts, as in:
template <Flavor F> void printPlumNumber(Number<F> num) {
static_assert(F == Plum, "Wrong number flavor!");
cout << num << endl;
}
This fails because regardless of the actual value of F, Number<F> is still just double and so I get an error about not being able to infer the value of F.
Elsewhere someone suggests explicit specialization, which also fails for this case:
template <Flavor F> void printRaspberryNumber(Number<F> num) = delete;
template <> void printRaspberryNumber<Raspberry>(Number<Raspberry> num) {
cout << num << endl;
}
Here, the compiler treats the call as ambiguous, in part again because it can't infer a value for F.
Elephant in the Room
I could, of course, make Number a single-value struct in the form of
template <Flavor> struct Number { double value; };
but I'm trying to avoid this option because I'm not terribly thrilled about the idea of having .value all over everywhere in my code, nor am I especially eager to define operators for Number that just proxy down to double.
Obligatory ideone
http://ideone.com/4HiYtI

The problem with this approach:
enum Flavor { Cherry, Plum, Raspberry };
template <Flavor> using Number = double;
is that alias templates are transparent. Number<Cherry>, Number<Plum>, and double are all the same type. That doesn't solve your problem at all.
What you want is typically called an opaque typedef. You really do want your last option:
template <Flavor>
struct Number {
double value;
operator double() const { return value; } // for convenience
Number& operator=(double ); // if necessary
// possibly more operations
};
This way, Number<Cherry> and Number<Plum> are different types. They are not convertible to each other. And double is not implicitly convertible to either.
You can also take a look at BOOST_STRONG_TYPEDEF and its implementation, it's intended to solve this problem too.

The option you're trying to avoid is really the only way to do this.
A template alias is what it is: an alias. A template alias is equivalent to the underlying type. In all respects.
template <Flavor> using Number = double;
This means that Number<Flavor> is a double. It is not anything else. Number<Plum> is a double, too. This is pretty much the same as doing a global search/replace of either one of them to double. The end result will be identical. The type is exactly the same.
You can only "declare a function that will only accept" a specific type. Except using a template alias, the template alias is the same type, as such it is not possible to declare a function that accept a double, but does not accept a double. It is a logical falsity.
Wrapping a double in a struct is the only way to achieve strict type checking, of this kind. It's not that bad. Toss in a few overloads, a few operators, and your wrapped struct will enforce strict type checking, and the compiler is likely to produce identical code, with no runtime penalty.

Related

Why is no deduction for template parameters only used as return type?

If I do not use tempate parameter (type) in a function argument list -> only as return type, then there is no deduction:
template <typename T>
T zero() { return 0; }
int main()
{
int x = zero();
}
gives:
a.cpp:15:18: error: no matching function for call to ‘zero()’
int x = zero();
^
a.cpp:11:3: note: candidate: ‘template<class T> T zero()’
T zero() { return 0; }
^~~~
a.cpp:11:3: note: template argument deduction/substitution failed:
a.cpp:15:18: note: couldn't deduce template parameter ‘T’
int x = zero();
The only way to compile, is to specify the template type in angle brackets:
template <typename T>
T zero() { return 0; }
int main()
{
int x = zero<int>();
}
So my question is, why g++ can deduce the type from argument list of template function, but cannot deduce it from return type (which is also known for compiler when compiling main, so it knows the type).
providing the type in angle brackets for template function is then arbitrary (because of deduction), when the template function uses template types in its argument list? So as a good practise, should I always provided the type in curly braces, no matter how the function is declared?
The second question is not readable much. Put it in simple words -> should I use foo<T>(arg, ...) (provide the type) everytime, no matter the function declaration? Even if it can be deduced by the compiler, but I will provided the type anyway for good practise?
Generally it is not possible to deduce function based on its return type. But if you use automatic types conversion c++ feature then you could achieve what you need:
template <typename T>
T zero() { return 1; }
template <>
float zero<float>() { return 3.0f; }
struct Zero
{
template<typename T>
operator T()
{
return zero<T>();
}
};
int main()
{
int x = Zero();
float y = Zero();
return x + y;
}
First you create temporary object Zero(), and during assigment we use conversion operator to execute correct specialization of zero template function.
So my question is, why g++ can deduce the type from argument list of template function
GCC follows the rules set forth by the C++ standard.
should I use foo(arg, ...) (provide the type) everytime, no matter the function declaration?
That depends on what you want to achieve. If you want to be explicit, do so. That would be similar to calling a foo_T() function in C which does not have templates nor overloads. However, if you want your code to be generic (for instance, because it is called in a template itself or because you want it easier to change on future type changes), then you would prefer to avoid writing the type explicitly.
Another option is using overloading rather than a template. Which one you use, again, depends on what you want and your use case.
Finally, you can also use auto instead:
auto zero() { return 0; }
Having said that, for signatures/interfaces, I think the best is to use explicit types everywhere unless there is a reason not to (e.g. it needs to be a template):
int zero() { return 0; }
Question 1
While it might be relatively easy to modify rules in yout trivial cases, this is not the case generally.
Consider a case like that:
template <A, B, C> A f(B b, C c) { ... } // #1
int f(int a, int b) { ... } // #2
int f(int a, double b) { ... } // #3
And a call like that:
double x = f(1, 2.0); // Call #1 or #3?
Thus it is not always trivial to modify rules and ensure that existing code continue to works. Such changes could easily lead to ambiguities, silent change of function being called...
Standard usually avoid modifying language in a way that could make unexpected silent changes (or make legal code become ambiguous).
However, it could be nice if there was a way to specify that we want deduction for return type in specific cases. By using a contextual keyword, rules could be defined on how to handled cases like the above one. For example, it could be a conflict if using return type deduction prefer an overload that is not the same one as without return type deduction.
Question 2
No, you should not generally provide the type if not needed.
Alternatives
While the solution to returns an object of a class with conversion operators could works, in may cases, them simplest solution would be to change the return value for an output parameter.
template <class T> void zero(T &t) { t = 0; } // set_zero would be more readable
int x;
zero(x);
I would not consider that solution appropriate for that case as the following is much clearer:
auto x = zero<int>();
In practice, given that the default value is zero for numerical types and for most other types, then cannot be initialized from an integer or it might not have the intended result, it would be better to simply write:
int x = {};
or
int x {};
It wouldn't have been impossible to define language rules to satisfy this case, but it would have been non-trivial and completely pointless.
This function has no business being a template, when all the information needed to decide its template argument is in the function. It should just return int, period. If you don't want to spell out the return type for whatever reason, this is what auto is for: it'll perform the deduction you seek.
On the other hand, if you want the 0 to be converted to different types for you depending on the template argument, then that makes more sense, and you already have the solution to that: provide the template argument (how could the computer guess it?). In this particular example you'd be better off just converting at the callsite, but presumably you have some more complex logic in mind.
As for whether you should always give template arguments explicitly, even when they are deducible, I'd say this is to some degree a matter of style. On the other hand it seems pretty pointless and noisy, but on the other it can be self-documenting and ensure that you're invoking the specialisation that you think you're invoking. So I think that this is going to depend on context.

Trailing return type deduced from input arguments concrete use-case

I have seen that one of the always given reasons of using trailing return types is when we want to deduce the return type from the input arguments.
I know there are other reasons but I'm focusing this specific one in this question.
One of the given example is:
template <typename T>
auto func(const T & t) -> decltype(std::cout << t)
{
return std::cout << t;
}
But I could not figure out any concrete use-case of this.
I mean, we always know the return type of a function when we write it, I can't find any concrete example when deducing the return type from arguments is really needed and cannot be avoided.
We can always (if I'm not mistaken) rewrite the function's prototype by directly specifying the return type without any deduction which makes it more concise and clearer in my sense.
The above example can be rewritten as:
template <typename T>
std::ostream& func(const T & t)
{
return std::cout << t;
}
In my opinion, this is less verbose and more readable than the trailing return type version.
What am I missing ?
I mean, we always know the return type of a function when we write it
Do we? So If you write this function template:
template<typename A, typename B>
/* ret */ foo(A a, B b) {
return a + b;
}
You can say for sure what ret is? If given two integer then it's an integer, sure. But if provided an integer and a long, it should be long due to promotions. And if one argument is a double, than the result should be a double two.
And what if that's two objects of some class types? Now we are calling an overloaded operator+, and there's absolutely no guessing what it may return.
I hope your'e convinced now that by saying we accept any two types, we cannot always be sure what is the type of an expression involving those types.
So a mechanism was added to the language to tell. Granted, this example is overly simple and is likely superseded by auto return types, but the general principle remains. When writing generic code, we often deal with unknown types. There is almost no knowing what should be the type of an expression involving them, or even if an expression like that is valid before the function is instantiated. decltype tells us that.
The above example can be rewritten as:
No it cannot. Your conclusion is based on the assumption that there is a:
std::ostream& operator<<(std::ostream&,const T&);
But this need not be the case. It could be a
any_other_type operator<<(std::ostream&,const T&);
Then your version of the method would fail to compile, while the one with deduced return type would be fine.
For a concrete use case, consider some kind of io-manipulation that lets you write code such as
std::cout << all_caps_modifier << "some text" << back_to_normal_modifier << " more text";
That would print:
SOME TEXT more text
I admit this is a rather contrived example, but using some proxy that encapsulates std::cout and makes the string getting printed in capital letters is a possible way to implement it ( std::cout << all_caps_modifier would return a type different from std::ostream&).

C++14 Variable Templates: what is their purpose? Any usage example?

C++14 will allow the creation of variables that are templated. The usual example is a variable 'pi' that can be read to get the value of the mathematical constant π for various types (3 for int; the closest value possible with float, etc.)
Besides that we can have this feature just by wrapping a variable within a templated struct or class, how does this mix with type conversions? I see some overlapping.
And other than the pi example, how would it work with non-const variables? Are there any usage examples to understand how to make the most of such a feature and what its purpose is?
And other than the pi example, how would it work with non-const
variables?
Currently, it seems to instantiate the variables separately for the type. i.e., you could assign 10 to n<int> and it would be different from the template definition.
template<typename T>
T n = T(5);
int main()
{
n<int> = 10;
std::cout << n<int> << " "; // 10
std::cout << n<double> << " "; // 5
}
If the declaration is const, it is readonly. If it's a constexpr, like all constexpr declarations, it has not much use outside constexpr(ressions).
Besides that we can have this feature just by wrapping a variable
within a templated struct or class, how does this mix with type
conversions?
It's meant to be a simple proposal. I am unable to see how it affects type conversions in a significant way. As I already stated, the type of the variable is the type you instantiated the template with. i.e., decltype(n<int>) is int. decltype((double)n<int>) is double and so on.
Any usage example to understand how to make the most of such a feature
and what its purpose is?
N3651 provides a succinct rationale.
Alas, existing C++ rules do not allow a template declaration to
declare a variable. There are well known workarounds for this
problem:
• use constexpr static data members of class templates
• use constexpr function templates returning the desired values
These workarounds have been known for decades and well documented.
Standard classes such as std::numeric_limits are archetypical
examples. Although these workarounds aren’t perfect, their drawbacks
were tolerable to some degree because in the C++03 era only simple,
builtin types constants enjoyed unfettered direct and efficient
compile time support. All of that changed with the adoption of
constexpr variables in C++11, which extended the direct and efficient
support to constants of user-defined types. Now, programmers are
making constants (of class types) more and more apparent in programs.
So grow the confusion and frustrations associated with the
workarounds.
...
The main problems with "static data member" are:
• they require "duplicate" declarations: once inside the class
template, once outside the class template to provide the "real"
definition in case the con- stants is odr-used.
• programmers are both miffed and confused by the necessity of providing twice the same
declaration. By contrast, "ordinary" constant declarations do not need
duplicate declarations.
...
Well known examples in this category are probably static member
functions of numeric_limits, or functions such as
boost::constants::pi<T>(), etc. Constexpr functions templates do not
suffer the "duplicate declarations" issue that static data members
have; furthermore, they provide functional abstraction. However, they
force the programmer to chose in advance, at the definition site, how
the constants are to be delivered: either by a const reference, or by
plain non- reference type. If delivered by const reference then the
constants must be systematically be allocated in static storage; if
by non-reference type, then the constants need copying. Copying isn’t
an issue for builtin types, but it is a showstopper for user-defined
types with value semantics that aren’t just wrappers around tiny
builtin types (e.g. matrix, or integer, or bigfloat, etc.) By
contrast, "ordinary" const(expr) variables do not suffer from this
problem. A simple definition is provided, and the decision of
whether the constants actually needs to be layout out in storage only
depends on the usage, not the definition.
we can have this feature just by wrapping a variable within a templated struct or class
Yes, but that would be gratuitous syntactic salt. Not healthy for the blood pressure.
pi<double> conveys the intent better than pi<double>::value. Short and to the point. That's enough of a reason in my book to allow and encourage this syntax.
Another practical example for C++14's variable templates is when you need a function for passing something into std::accumulate:
template<typename T>
T const & (*maxer) (T const &, T const &) = std::max<T>;
std::accumulate(some.begin(), some.end(), initial, maxer<float>);
Note that using std::max<T> is insufficient because it can't deduce the exact signature. In this particular example you can use max_element instead, but the point is that there is a whole class of functions that share this behavior.
I wonder whether something along these lines would be possible: (assuming availability of template lambdas)
void some_func() {
template<typename T>
std::map<int, T> storage;
auto store = []<typename T>(int key, const T& value) { storage<T>[key] = value; };
store(0, 2);
store(1, "Hello"s);
store(2, 0.7);
// All three values are stored in a different map, according to their type.
}
Now, is this useful?
As a simpler use, notice that the initialization of pi<T> uses explicit conversion (explicit call of a unary constructor) and not uniform initialization. Which means that, given a type radians with a constructor radians(double), you can write pi<radians>.
Well, you can use this to write compile time code like this:
#include <iostream>
template <int N> const int ctSquare = N*N;
int main() {
std::cout << ctSquare<7> << std::endl;
}
This is a significant improvement over the equivalent
#include <iostream>
template <int N> struct ctSquare {
static const int value = N*N;
};
int main() {
std::cout << ctSquare<7>::value << std::endl;
}
that people used to write to perform template metaprogramming before variable templates were introduced. For non-type values, we were able to do this since C++11 with constexpr, so template variables have only the advantage of allowing computations based on types to the variable templates.
TL;DR: They don't allow us to do anything we couldn't do before, but they make template metaprogramming less of a PITA.
I have a use case here.
template<typename CT> constexpr CT MARK = '%';
template<> constexpr wchar_t MARK<wchar_t> = L'%';
which are used in a string processing template.`
template <typename CT>
void ProcessString(const std::basic_string<CT>& str)
{
auto&& markpos = str.find(MARK<CT>);
...
}

Reason for using non-type template parameter instead of regular parameter?

In C++ you can create templates using a non-type template parameter like this:
template< int I >
void add( int& value )
{
value += I;
}
int main( int argc, char** argv )
{
int i = 10;
add< 5 >( i );
std::cout << i << std::endl;
}
Which prints "15" to cout. What is the use for this? Is there any reason for using a non-type template parameter instead of something more conventional like:
void add( int& value, int amount )
{
value += amount;
}
Sorry if this has already been asked (I looked but couldn't find anything).
There are many applications for non-type template arguments; here are a few:
You can use non-type arguments to implement generic types representing fixed-sized arrays or matrices. For example, you might parameterize a Matrix type over its dimensions, so you could make a Matrix<4, 3> or a Matrix<2, 2>. If you then define overloaded operators for these types correctly, you can prevent accidental errors from adding or multiplying matrices of incorrect dimensions, and can make functions that explicitly communicate the expected dimensions of the matrices they accept. This prevents a huge class of runtime errors from occur by detecting the violations at compile-time.
You can use non-type arguments to implement compile-time function evaluation through template metaprogramming. For example, here's a simple template that computes factorial at compile-time:
template <unsigned n> struct Factorial {
enum {
result = n * Factorial<n - 1>::result
};
};
template <> struct Factorial<0> {
enum {
result = 1
};
};
This allows you to write code like Factorial<10>::result to obtain, at compile-time, the value of 10!. This can prevent extra code execution at runtime.
Additionally, you can use non-type arguments to implement compile-time dimensional analysis, which allows you to define types for kilograms, meters, seconds, etc. such that the compiler can ensure that you don't accidentally use kilograms where you meant meters, etc.
Hope this helps!
You're probably right in this case, but there are cases where you need to know this information at compile time:
But how about this?
template <std::size_t N>
std::array<int, N> get_array() { ... }
std::array needs to know its size at compile time (as it is allocated on the stack).
You can't do something like this:
std::array<int>(5);
Well, this the typical choice between compile-time polymorphism and run-time polymorphism.
From the wording of your question in appears that you see nothing unusual in "ordinary" template parameters, while perceiving non-type parameters as something strange and/or redundant. In reality the same issue can be applied to template type parameters (what you called "ordinary" parameters) as well. Identical functionality can often be implemented either through polymorphic classes with virtual functions (run-time polymorphism) or through template type parameters (compile-time polymorphism). One can also ask why we need template type parameters, since virtually everything can be implemented using polymorphic classes.
In case of non-type parameters, you might want to have something like this one day
template <int N> void foo(char (&array)[N]) {
...
}
which cannot be implemented with a run-time value.
In that particular instance, there's not really any advantage. But using template parameters like that, you can do a lot of things you couldn't do otherwise, like effectively bind variables to functions (like boost::bind), specify the size of a compile-time array in a function or class (std::array being a ready example of that), etc.
For instance, with that function, you write a function like
template<typename T>
void apply(T f) {
f(somenum);
}
Then you can pass apply a function:
apply(&add<23>);
That's an extremely simple example, but it demonstrates the principle. More advanced applications include applying functions to every value in a collection, calculating things like the factorial of a function at compile time, and more.
You couldn't do any of that any other way.
There are lots of reasons, like doing template metaprogramming (check Boost.MPL). But there is no need to go that far, C++11's std::tuple has an accessor std::get<i> that needs to be indexed at compile time, since the result is dependent on the index.
The most frequent use for a value parameter that I can think of is std::get<N>, which retrieves the Nth element of a std::tuple<Args...>. The second-most frequent use would be std::integral_constant and its main derivatives std::true_type and std::false_type, which are ubiquitous in any sort of trait classes. In fact, type traits are absolutely replete with value template parameters. In particular, there are SFINAE techniques which leverage a template of signature <typename T, T> to check for the existence of a class member.

C++ Types Impossible to Name

While reading Wikipedia's page on decltype, I was curious about the statement,
Its [decltype's] primary intended use is in generic
programming, where it is often
difficult, or even impossible, to name
types that depend on template
parameters.
While I can understand the difficulty part of that statement, what is an example where there is a need to name a type that cannot be named under C++03?
EDIT: My point is that since everything in C++ has a declaration of types. Why would there ever be a case where it is impossible to name a type? Furthermore, aren't trait classes designed to yield type informations? Could trait classes be an alternative to decltype?
The wikipedia page you link has a perfect example:
int& foo(int& i);
float foo(float& f);
template <class T> auto transparent_forwarder(T& t) −> decltype(foo(t)) {
return foo(t);
}
Note that foo(int&) returns int& (a reference type) while foo(float&) returns float (a nonreference type). Without decltype, it's impossible within the template to specify a type which represents "the return type of the function foo which takes an argument t of type T".
In this example, it's not a particular concrete type which is impossible to express -- either int& or float are individually expressible -- but a higher level generic class of types.
EDIT: and to answer your comment to another answer, this example is inexpressible in C++03. You cannot have a function template which will wrap any function T1 foo(T2) and match both argument and return type of the wrapped function.
There are types in C++0x (and in C++03, but less often) that cannot be named explicitly, such as the type decltype(f) after the declaration auto f = [](int x) -> int {return x;};. You would need to typedef that decltype result to something to get a name at all. Traits classes can be used for determining return types, but they are messy, and the user needs to duplicate all of their function overloads with traits class overloads; that is difficult to do correctly for cases such as functions applying (through implicit conversion of pointers) to all subclasses of a given base class.
As you pointed out, the type if it exist is known by the compiler, otherwise it wouldn't exist. However, it is not always readily or even accessible to the programmer in C++03.
N1607 mention the following in its conclusion:
In C++2003, it is not possible to
express the return type of a function
template in all cases. Furthermore,
expressions involving calls to
function templates commonly have very
complicated types, which are
practically impossible to write by
hand
The question is how do we access this type as a programmer. This is not always a trivial process, often impracticable. It is increasingly complex when you have an expression for which you desire to know the result type. You would have to break it into pieces in order to figure the result types. It is not possible to simplify this process using templates (not without evaluating the expression anyhow). Breaking the expression will be error-prone, tedious and a nightmare to maintain. Think of this code:
x.g()[b.a(e)]->f();
With C++98/TR1, it is often infeasible to name types that depend on template parameters. Traits offers us so much information, but eventually decltype is a much cleaner solution to many problems. A lot of the information available to you when meta programming is only available because libraries, such as boost or loki, use several tricks hidden in the dark corners of the C++98 language.
Of course this is irrelevant to your question but I believe that it is worthy to mention that C++98 compilers already have mechanics to know these types. This is exactly what sizeof offers, except that it returns you a size. decltype reuse some of this functionality and solves these problems with greater elegance.
As for a different (academic) example:
struct Foo
{
struct
{
int x;
} bar;
};
template<typename T>
void
f(const T& t)
{
// C++03, How can I name the type of T::bar ?
// C++0x
// decltype(t.bar) cpy;
// Do stuff with our local cpy
}
int
main()
{
f(Foo());
}