带有功能模板重载的基于SFINAE的特征实现问题

问题描述 投票:0回答:1

我正在学习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;
}

结果始终为false false,而如果我使用其他参数化子句(未注释掉的子句),则程序将按预期给出true,false。那么,为什么带有非类型参数的子句总是会被SFINAE淘汰呢?

c++ templates overloading traits sfinae
1个回答
0
投票

作为非类型模板参数的引用类型必须是具有静态存储持续时间(即全局变量)的对象的名称。有关原因的详细信息,请参见https://stackoverflow.com/a/28728098/5754656

因此const U& = U()在模板中始终是无效的,因为U()不是变量的名称(它看起来像const U& = some_global_U_variable),因此不会在Test<T>(nullptr)中选择它。

© www.soinside.com 2019 - 2024. All rights reserved.