C++17中有条件启用的成员函数



假设类型可以有FooBarBaz方法,并且我们有类型特征来检查它。例如,对于Foo,我们有HasFoo:

template <class Type>
constexpr bool  DetectFoo (decltype (std::declval<Type> ().Foo ())*)    { return true; }
template <class Type>
constexpr bool  DetectFoo (...)                                         { return false; }
template <class Type>
constexpr bool  HasFoo = DetectFoo<Type> (nullptr);

让我们编写一个Wrapper<Type>类模板,它转发具有或不具有这些方法的Type的属性。对于任何Type,应满足以下条件:

  • Wrapper<Type> w;应该编译,因为我们还没有调用这些方法
  • w.X ();应该编译iffHasX<Type>,因为X=FooBarBaz
  • HasX<Wrapper<Type>> == HasX<Type>应保持,因为X=FooBarBaz

要有条件地启用Wrapper中的方法,在C++20中有一个明确的方法:

template <class Type>
struct Wrapper {
void Foo ()
requires HasFoo<Type>;
};

但是在没有概念的早期C++标准中该怎么办呢?我提出了以下想法(见现场演示(:

template <class Type>
struct Wrapper {
template <bool dummy = true, class = std::enable_if_t<HasFoo<Type> && dummy>>
void Foo ();
};

这个答案说这是不正确的,NDR,但我不明白解释。这真的不正规吗,NDR?

您的代码格式良好。

链接的答案指[temp.res.general]/8.1:

模板的有效性可以在任何实例化之前进行检查。。。程序格式错误,无需诊断,如果:

--无法为模板生成有效的专用化。。。并且模板没有被实例化。。。

这里;模板";我们说的是CCD_ 23。

我相信这可以用两种方式来解释:

(1( 我们可以认为Wrapper<A>::FooWrapper<B>::Foo是相同的模板(对于每个AB(。然后,Wrapper的模板自变量的存在使得enable_if_t中的条件true足以使代码良好地形成。

(2( 我们还可以将Wrapper<A>::FooWrapper<B>::Foo视为不同的模板(对于A != B(。然后,如果Wrapper存在这样一个无法实例化Foo的模板参数,那么您的代码将是格式错误的NDR。但这永远不会发生,因为对于每个模板参数,您总是可以将HasFoo专门化为true

无论如何,我认为(1(是预期的解释。[temp.res.general]/8.1的目的不是妨碍您,而是通过尽早验证模板来帮助您。我从未见过编译器使用第二种解释。

相关内容

  • 没有找到相关文章

最新更新