【问题标题】:SFINAE based traits implementation issue with function template overload函数模板重载的基于 SFINAE 的特征实现问题
【发布时间】:2020-05-27 22:26:36
【问题描述】:

我正在学习有关 SFINAE 和特征的知识,并且我知道我可以定义基于 SFINAE 的特征(在其实现中使用 SFINAE 的特征)。检测类型是否默认可构造的特征的经典实现是:

template <typename T>
struct IsDefaultConstructibleH
{
private:
    template <typename U, typename = decltype(U())>
    //template <typename U, const U& = U()>   // WHY IS THIS ALWAYS SFINAE'd out?
    static TrueType Test(void*);
    template <typename>
    static FalseType Test(...);
public:
    using Type = decltype(Test<T>(nullptr));
};

template <typename T>
struct IsDefaultConstructible : IsDefaultConstructibleH<T>::Type
{
};

template <typename T>
constexpr bool IsDefaultConstructibleV = IsDefaultConstructible<T>::Value;

正如我在上面的代码中指出的,如果我使用注释掉的模板参数化子句(并注释掉上面的那个),如果我运行这段代码:

#include "traits.hpp"
#include <iostream>

class Default
{
public:
    Default() : mData(10) {}
private:
    int mData;
};

class NoDefault
{
public:
    NoDefault(int i) : mData(i) {}
private:
    int mData;
};

int main(int argc, char ** argv)
{
    std::cout << std::boolalpha << IsDefaultConstructible<Default>::Value << std::endl;
    std::cout << std::boolalpha << IsDefaultConstructibleV<NoDefault> << std::endl;

    return 0;
}

结果总是假假,而如果我使用另一个参数化子句(未注释掉的那个),程序会按预期给出真假。那么为什么带有非类型参数的子句总是被 SFINAE 淘汰呢?

【问题讨论】:

    标签: c++ templates overloading traits sfinae


    【解决方案1】:

    作为非类型模板参数的引用类型必须是具有链接的对象的名称(通常是全局变量)。见https://en.cppreference.com/w/cpp/language/template_parameters#Template_non-type_arguments。它特别不能是临时的。

    因此const U&amp; = U() 在模板中总是无效的,因为U() 不是变量的名称(它应该看起来像const U&amp; = some_global_U_variable)所以它不会在Test&lt;T&gt;(nullptr) 中被选中。

    【讨论】:

      猜你喜欢
      • 2018-08-16
      • 2019-07-19
      • 2017-02-23
      • 1970-01-01
      • 2018-09-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-16
      相关资源
      最近更新 更多