`nullopt`可以作为非类型模板参数传递吗?

bmk*_*bmk 5 c++ c++17

请考虑以下代码示例

#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
}
Run Code Online (Sandbox Code Playgroud)

我想要实现的是nullopt作为非类型函数模板参数传递但它不编译.它适用于dflt具有静态存储的全局变量.

编译器错误消息如下所示:

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>();
Run Code Online (Sandbox Code Playgroud)

我知道这个例子很傻,但我的主要问题是,可以nullopt作为非类型模板参数传递吗?

Sto*_*ica 6

不是你尝试传递它的方式.

更长的答案与模板参数的约束有关.您的模板参数是引用类型.它的相应参数必须满足[temp.arg.nontype]/2(强调我的)中的要求:

非类型模板参数的模板参数应该是模板参数类型的转换常量表达式.对于引用或指针类型的非类型模板参数,常量表达式的值不应引用(或者对于指针类型,不应该是地址):

  • 一个子对象,
  • 一个临时对象,
  • 一个字符串文字,
  • typeid表达式的结果,或
  • 预定义的 func__变量.

nullopt是类型的常量nullopt_t.这显然不是一个optional<int>.因此,要绑定该const引用,我们需要实现一个临时的.但这显然使程序格式不正确,正如粗体文字所示.


但请注意,您可以将参数作为对a的引用nullopt_t.然后你可以传递nullopt参数.虽然这种模板的实用性有限,但我会说.