Every self-respecting C/C++ programmer knows what the ternary operator is, and most everyone used it at least once in their programs. But do you know all the secrets of the ternary operator? What potential dangers are associated with its use and what features, seemingly not related to its direct purpose, it has? This article gives you the opportunity to test your knowledge and maybe learn something new.

## Test

Will the following code compile? Explain why.

1.

``````int i;
int j;
(false ? i: j) = 45;``````

2.

``````int i;
int j;
(true ? i: j) = 45;``````

3.

``````short i;
int j;
(true ? i: j) = 45;``````

4.

``return true ? 0 : 1;``

5.

``true ? return 0 : return 1;``

6. What will be the output of the following piece of code? Why?

``std::cout << (false ? 9 : '9') << " " << (true ? 9 : '9');``

7. What values will have variables a, b and c as a result of the following code execution? Why?

``````int a = 1;
int b = 1;
int c = 1;
a = true ? ++b : ++c;``````

8. Name a situation, in which you cannot useif{...} else{...}, but can use the ternary operator.

9. What are the potential dangers hiding in the use of the ternary operator What is the cause?

10. What unexpected use of the ternary operator comes to your mind?

## Explanation

So, let’s start. The ternary operator stands out from other operators in C++. It is called the "conditional expression". Since it’s an expression, it should also have the type and value category, just like any other expression. Actually, if we answer the questions about the type and the value category of the ternary operator in each of the first seven questions of the test, it will be pretty easy to solve them.

Here comes the fun part. It turns out that the type of the ternary operator is the most common type of his last two operands. What does the most common mean? The easiest way to explain this is to use examples. The common type of int and short is int.

The common type of A and B in the next fragment of code is also int.

``````struct A{ operator int(){ return 1; } };
struct B{ operator int(){ return 3; } };``````

Thus, the most common type is the type, which both operands can be converted to. There can be situations when there’s no common type. For example,

``````struct C{};
struct D{};``````

have no common type, and the following code will not compile:

``(true ? C() : D());``

I guess the type of the ternary operator is clear now. Now, let’s talk about the value category. The following rule applies here: if types in the ternary operator are converted to the most common one, the ternary operator is rvalue. If not, it is lvalue. Knowing this, we can easily answer the first 7 questions.

1. and 2. — Yes, it will. Types are not converted, and it’s quite possible to assign a value to lvalue.

3. — No, it won’t compile. The conversion of types takes place here, which means that the value category of the expression on the left from "=" is rvalue. As you know, rvalue can not be assigned.

4. — Yes, it will. All of us have done so more than once.

5. — No, it won’t. The thing is that a statement cannot break an expression in С++.

6. The program will print “57 9”. Since the 2nd and the 3rd operands are of different types, the conversion to the most common type takes place here. In the given case, it is int. And, as we know, '9' has ASCII code 57.

7. Another feature of the ternary operator is hiding in this question. Namely, out of the second and the third operands, the only one is being computed — the operand reached by the execution thread.

However, the same behavior can be observed in if {...} else {...}. Thus, the values of variables a, b and с will be 2, 2, 1.

### In what situations we can't use if {...} else {...}, but can use the ternary operator?

For instance, when initializing constructor. We cannot write the following:

``````struct S
{
S() : if(true) i_(1) else i_(0){}
int i_;
};``````

But we can do it like this:

``````struct S
{
S() : i_(some_condition ? 0 : 1){}
int i_;
};``````

That is to say, during the initialization of a reference depending on the condition. As we know, we cannot declare an uninitialized reference. Therefore, the following code fragment will not compile:

``````int a = 3;
int b = 4;
int& i;
if(some_condition)
i = a;
else
i = b;``````

While this fragment will compile successfully:

``int& i = (some_condition ? a : b);``

In C++11, the ternary operator is applied much more often. That's because the constexpr functions should have nothing but the return `expression`. While the `expression` may well be a ternary operator.

As an example, I’ll provide a classic algorithm for determining the primality of a number.

``````constexpr bool check_if_prime_impl(unsigned int num, unsigned int d)
{
return (d * d > num) ? true :
(num % d == 0) ? false :
check_if_prime_impl(num, d + 1);
}
constexpr bool check_if_prime(unsigned int num)
{
return (num <= 1) ? false :
check_if_prime_impl(num, 2);
}``````

By the way, the same example shows the use of nested ternary operators, where multiple ternary evaluations are also possible, so that to avoid multiple if {...} else {...} (don't drink too much kool-aid — for the sake of readability, if {…} else {…} might be a better choice).

### Dangers of the Ternary Operator

Suppose we have a String class

``````class String
{
public:
operator const char*();
};``````

and we can use it like this:

``const char* s = some_condition ? "abcd" : String("dcba");``

As we already know, the second and third operands of the ternary operator are converted to the most common type. In this case, it is const char*. But the String(«dcba») object will be destroyed at the end of the expression, and s will point to the invalid memory. In the best case, the program will crash trying to use s later. In the worst case, it will produce wrong results, causing dissatisfaction among customers and a headache for the programmer.

### An “Unusual” Use of the Ternary Operator

We can use the ternary operator to determine the common type of two and more types. This can also be used to determine whether one type is converted to the other one.

``````template
struct common_type
{
typedef decltype(true ? std::declval() : std::declval()) type;
};
template
struct is_same{ enum { value = false; } };
template
struct is_same{ enum { value = true; } };
int main()
{
std::cout << is_same::type>::value <``````
``` In fact, if you know the features of the ternary operator, such usage almost suggests itself. The unusual thing here is perhaps that it is not used for the intended purpose, i.e. not for selecting one value out of two, depending on the condition. ```
``` START WRITING AT KUKURUKU HUB (adsbygoogle=window.adsbygoogle||[]).push({}); READ NEXT I Do Not Know C Lock-Free Data Structures. The Evolution of a Stack Quantum Search Using Grover’s Algorithm A Short Course in Computer Graphics. How to Write a Simple OpenGL. Article 1 of 6 USB Killer A Short Course in Computer Graphics. How to Write a Simple OpenGL. Article 2 of 6 Undefined Behavior and Fermat’s Last Theorem Multitasking in the Linux Kernel. Workqueues Introduction to Machine Learning with Python and Scikit-Learn google_ad_client="ca-pub-5957750206575747";google_ad_slot="4872645719";google_ad_width=300;google_ad_height=250; 8169 1 Published by Kukuruku Hub RATING: 13.90 Published in C++C++ is a high-level programming language developed by Bjarne Stroustrup. But you know that, right? 0  Written by Alex Kulikov 1 ```
``` Subscribe to Kukuruku Hub Or subscribe with RSS 1 comment Mironov Andrey 8 March 2015, 7:31 AM ↓    The following rule applies here: if types in the ternary operator are converted to the most common one, the ternary operator is rvalue. Imagine a situation where both types can be converted to some common lvalue reference type. I speak types with user-defined conversion operators. Upload image From PC From internet File Align No Left Right Center Title Image URL Align No Left Right Center Title or jQuery(function(\$){ls.lang.load({"panel_b":"bold","panel_i":"italic","panel_u":"underline","panel_s":"strike through","panel_url":"type link","panel_url_promt":"Type link","panel_code":"code","panel_video":"video","panel_image":"image","panel_cut":"cut","panel_quote":"quote","panel_list":"List","panel_list_ul":"UL LI","panel_list_ol":"OL LI","panel_title":"Header","panel_clear_tags":"clean up the tags","panel_video_promt":"Enter a link to the video","panel_list_li":"list item","panel_image_promt":"Enter the link to an image","panel_user":"user inserted","panel_user_promt":"Enter the user login"});\$('.markitup-editor').markItUp(ls.settings.getMarkitupComment());}); Read Next AVL Trees 19628 C++ Comparing Rust and C++ 37845 Rust Randomized Binary Search Trees 9452 C++ About Rules Privacy Policy · Twitter Facebook Log In Remember me Forgot password? ﻿ or Sign in with Github Sign in with Twitter var fbAppId='1446177405629271';var fbLoginPath='https://kukuruku.co/login/'+'openid/fb/';var fbScope='user_birthday,user_website,email,user_about_me';var sTwitterLoginPath='https://kukuruku.co/login/'+'openid/twitter/?authorize=1';var base_redir_url="https://kukuruku.co/login/openid/enter/";function getEl(id){return document.getElementById(id);} function openid_google(){getEl('open_login').value='https://www.google.com/accounts/o8/id';authRedir();} function authRedir(){if(getEl('open_login').value){str=base_redir_url+"?submit_open_login=go&open_login="+getEl('open_login').value+"&return="+getEl('rreturn').value;openid_setCookie("openid_referrer",window.location.href,1);window.location=str;}else{alert('OpenID has not been specified');}} function fb_open(){openid_setCookie("openid_referrer",window.location.href,1);window.location='https://www.facebook.com/dialog/oauth?client_id='+fbAppId+'&redirect_uri='+fbLoginPath+'&scope='+encodeURI(fbScope);} function openid_twitter(){openid_setCookie("openid_referrer",window.location.href,1);window.location=sTwitterLoginPath;} function openid_setCookie(c_name,value,exdays) {var exdate=new Date();exdate.setDate(exdate.getDate()+exdays);var c_value=escape(value)+((exdays==null)?"":";expires="+exdate.toUTCString())+";path=/";document.cookie=c_name+"="+c_value;} \$('.btn-social').click(function(){\$(this).attr('disabled','disabled');}); Don't have an account? Sign up now Sign Up ﻿ or Sign in with Github Sign in with Twitter var fbAppId='1446177405629271';var fbLoginPath='https://kukuruku.co/login/'+'openid/fb/';var fbScope='user_birthday,user_website,email,user_about_me';var sTwitterLoginPath='https://kukuruku.co/login/'+'openid/twitter/?authorize=1';var base_redir_url="https://kukuruku.co/login/openid/enter/";function getEl(id){return document.getElementById(id);} function openid_google(){getEl('open_login').value='https://www.google.com/accounts/o8/id';authRedir();} function authRedir(){if(getEl('open_login').value){str=base_redir_url+"?submit_open_login=go&open_login="+getEl('open_login').value+"&return="+getEl('rreturn').value;openid_setCookie("openid_referrer",window.location.href,1);window.location=str;}else{alert('OpenID has not been specified');}} function fb_open(){openid_setCookie("openid_referrer",window.location.href,1);window.location='https://www.facebook.com/dialog/oauth?client_id='+fbAppId+'&redirect_uri='+fbLoginPath+'&scope='+encodeURI(fbScope);} function openid_twitter(){openid_setCookie("openid_referrer",window.location.href,1);window.location=sTwitterLoginPath;} function openid_setCookie(c_name,value,exdays) {var exdate=new Date();exdate.setDate(exdate.getDate()+exdays);var c_value=escape(value)+((exdays==null)?"":";expires="+exdate.toUTCString())+";path=/";document.cookie=c_name+"="+c_value;} \$('.btn-social').click(function(){\$(this).attr('disabled','disabled');}); Already have an account? Log in here Reset Password Enter the email address associated with your account, and we'll email you a link to reset your password. Already have an account? Log in here window.doorbellOptions={appKey:'nVw5xydsqfYHCDW0snI2L7itP8MC1mSOcv7ED3WQMLJ27GC12mU7fCPTBj1p67ih'};(function(d,t){var g=d.createElement(t);g.id='doorbellScript';g.type='text/javascript';g.async=true;g.src='https://doorbell.io/button/926?t='+(new Date().getTime());(d.getElementsByTagName('head')[0]||d.getElementsByTagName('body')[0]).appendChild(g);}(document,'script')); //<![CDATA[ (function(){var d=encodeURIComponent,f=window,g=document,h="documentElement",k="length",l="prototype",m="body",p="&",s="&ci=",t=",",u="?",v="Content-Type",w="Microsoft.XMLHTTP",x="Msxml2.XMLHTTP",y="POST",z="application/x-www-form-urlencoded",A="img",B="input",C="load",D="oh=",E="on",F="pagespeed_url_hash",G="url=";f.pagespeed=f.pagespeed||{};var H=f.pagespeed,I=function(a,b,c){this.c=a;this.e=b;this.d=c;this.b=this.f();this.a={}};I[l].f=function(){return{height:f.innerHeight||g[h].clientHeight||g[m].clientHeight,width:f.innerWidth||g[h].clientWidth||g[m].clientWidth}};I[l].g=function(a){a=a.getBoundingClientRect();return{top:a.top+(void 0!==f.pageYOffset?f.pageYOffset:(g[h]||g[m].parentNode||g[m]).scrollTop),left:a.left+(void 0!==f.pageXOffset?f.pageXOffset:(g[h]||g[m].parentNode||g[m]).scrollLeft)}};I[l].h=function(a){if(0>=a.offsetWidth&&0>=a.offsetHeight)return!1;a=this.g(a);var b=a.top.toString()+t+a.left.toString();if(this.a.hasOwnProperty(b))return!1;this.a[b]=!0;return a.top<=this.b.height&&a.left<=this.b.width};I[l].i=function(a){var b;if(f.XMLHttpRequest)b=new XMLHttpRequest;else if(f.ActiveXObject)try{b=new ActiveXObject(x)}catch(c){try{b=new ActiveXObject(w)}catch(e){}}if(!b)return!1;b.open(y,this.c+(-1==this.c.indexOf(u)?u:p)+G+d(this.e));b.setRequestHeader(v,z);b.send(a);return!0};I[l].k=function(){for(var a=[A,B],b=[],c={},e=0;e<a[k];++e)for(var q=g.getElementsByTagName(a[e]),n=0;n<q[k];++n){var r=q[n].getAttribute(F);r&&(q[n].getBoundingClientRect&&this.h(q[n]))&&!(r in c)&&(b.push(r),c[r]=!0)}if(0!=b[k]){a=D+this.d;a+=s+d(b[0]);for(e=1;e<b[k];++e){c=t+d(b[e]);if(131072<a[k]+c[k])break;a+=c}H.criticalImagesBeaconData=a;this.i(a)}};H.j=function(a,b,c){if(a.addEventListener)a.addEventListener(b,c,!1);else if(a.attachEvent)a.attachEvent(E+b,c);else{var e=a[E+b];a[E+b]=function(){c.call(this);e&&e.call(this)}}};H.l=function(a,b,c){var e=new I(a,b,c);H.j(f,C,function(){f.setTimeout(function(){e.k()},0)})};H.criticalImagesBeaconInit=H.l;})();pagespeed.criticalImagesBeaconInit('/mod_pagespeed_beacon','https://kukuruku.co/hub/cpp/secrets-of-the-conditional-ternary-operator','al3hKzsAgw'); //]]> ```