Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can `nullopt` be passed as non-type template parameter?

Tags:

c++

c++17

Consider the following code example

#include <iostream>
#include <experimental/optional>

std::experimental::optional<int> dflt(42);

template<const std::experimental::optional<int>& Dflt>
void foo() {
    if (Dflt) {
        std::cout << "default is set" << std::endl;
    } else {
        std::cout << "default is not set" << std::endl;
    }
}

int main() {
        foo<dflt>();                       // <-- OK
        foo<std::experimental::nullopt>(); // <-- NOT OK
}

What I am trying to achieve is to pass nullopt as a non-type function template parameter but it doesn't compile. It works with a global variable dflt with static storage though.

The compiler error message looks like this:

foo.cc: In function ‘int main()’:
foo.cc:13:34: error: no matching function for call to ‘foo()’
  foo<std::experimental::nullopt>();
                                  ^
foo.cc:7:6: note: candidate: template<const std::experimental::fundamentals_v1::optional<int>& Dflt> void foo()
 void foo() {
      ^
foo.cc:7:6: note:   template argument deduction/substitution failed:
foo.cc:13:34: error: could not convert template argument ‘std::experimental::fundamentals_v1::nullopt’ to ‘const std::experimental::fundamentals_v1::optional<int>&’
  foo<std::experimental::nullopt>();

I know the example is silly, but my main question is, can nullopt be passed as non-type template parameter at all?

like image 832
bmk Avatar asked Mar 13 '18 08:03

bmk


People also ask

What is a non type template parameter?

A template non-type parameter is a template parameter where the type of the parameter is predefined and is substituted for a constexpr value passed in as an argument. A non-type parameter can be any of the following types: An integral type. An enumeration type. A pointer or reference to a class object.

What can the template parameter in C++ template definition be?

A template parameter is a special kind of parameter that can be used to pass a type as argument: just like regular function parameters can be used to pass values to a function, template parameters allow to pass also types to a function.

What is non type?

NoneType is the type for the None object, which is an object that indicates no value. None is the return value of functions that "don't return anything".

What is a template parameter?

In UML models, template parameters are formal parameters that once bound to actual values, called template arguments, make templates usable model elements. You can use template parameters to create general definitions of particular types of template.


1 Answers

Not the way you try to pass it.

The longer answer has to do with the constraints placed on template arguments. Your template parameter is of a reference type. The corresponding argument for it must fulfill the requirements in [temp.arg.nontype]/2 (emphasis mine):

A template-argument for a non-type template-parameter shall be a converted constant expression of the type of the template-parameter. For a non-type template-parameter of reference or pointer type, the value of the constant expression shall not refer to (or for a pointer type, shall not be the address of):

  • a subobject,
  • a temporary object,
  • a string literal,
  • the result of a typeid expression, or
  • a predefined ­­func_­_­ variable.

nullopt is a constant of the type nullopt_t. Which is quite plainly not an optional<int>. As such, to bind that const reference we will need to materialize a temporary. But that explicitly makes the program ill-formed, as the text in bold indicates.


Mind you however, that you can have the parameter be a reference to a nullopt_t. Then you can pass nullopt for the argument. Though the utility of such a template is limited, I'd say.

like image 172
StoryTeller - Unslander Monica Avatar answered Sep 29 '22 02:09

StoryTeller - Unslander Monica