This is no provide additional information for TEMLIB's answer without mutilating it. The information won't fit in a comment.
IEEE Std 1076-2008 9.2.9 Condition operator, paragraph 4:
The condition operator implicitly applied, if any, is either the predefined operator for type BIT or an overloaded operator, determined as follows. If, without overload resolution (see 12.5), the expression is of type BOOLEAN defined in package STANDARD, or if, assuming a rule requiring the expression to be of type BOOLEAN defined in package STANDARD, overload resolution can determine at least one interpretation of each constituent of the innermost complete context including the expression, then the condition operator is not applied. Otherwise, the condition operator is implicitly applied, and the type of the expression with the implicit application shall be BOOLEAN defined in package STANDARD.
Type BOOLEAN has the operator implemented in package standard:
ghdl --disp-standard --std=08 | grep \?\?
-- function "??" (<anonymous>: bit) return boolean;
It's also implemented in the -2008 revision of package std_logic_1164:
function "??" (l : STD_ULOGIC) return BOOLEAN;
Which serves for any array types or subtypes defined with STD_ULOGIC elements. (Array types ufixed, sfixed, float, signed, unsigned, std_ulogic_vector and std_logic_vector all use std_ulogic elements and are declared in IEEE packages).
There are no other types with the condition operator predefined in the -2008 revision of the standard.
The -2008 standard also introduces matching relational operators (See 9.2.3 Relational operators.
There is a downside. Just about every VHDL tool has to have -2008 compatibility mode enabled, and all new features aren't supported by all tools (presumptively not yet, it's only been eight years).
Which constructs you should use are generally dictated by your entire tool chain (especially synthesis tools) as well as portability concerns.
You'll find in Xilinx's supported features in User Guide 901 Vivado Design Suite User Guide Synthesis Chapter 5 VHDL-2008 Language Support. Other vendors will generally be forthcoming with feature support.
You could note The Designer's Guide to VHDL, Peter Ashenden, 2d ed., 2002 that the subject exercise the question is taken from precedes the release of the -2008 standard by more than six years.
Chapter 1 Exercise 8, Book page 26:
Write an entity declaration and a behavioral architecture body for a two-input multiplexer with input ports a, b and sel and an output port of z. If the sel input is '0' the value of a should be copied to z, otherwise the value of b should be copied to z. Write a test bench for the multiplexer model, and test it using a VHDL simulator."
I'd suggest putting all the shortcuts into practice immediately:
entity mul2 is
port ( a, b, sel: bit;
z : out bit );
architecture foo of mul2 is
Z <= a when sel else b;
doesn't serve the VHDL learner as well as understanding the syntax, semantics and type system nor understanding the limits of the tool chain he or she is using. If you don't understand VHDL sufficiently working around tool chain shortcomings can be much more difficult.
As well as an implicitly applied condition operator the condition expression could be explicitly applied: