C++ std::enable_if作为构造函数的单个参数

C++ std::enable_if作为构造函数的单个参数,c++,c++11,template-meta-programming,enable-if,C++,C++11,Template Meta Programming,Enable If,我对模板元编程相当陌生,并且一直在研究其中的一些概念——然而,我遇到的这个特殊片段让我有些困惑 template<class TAG, typename... DATATYPES> struct Message { Message (typename std::enable_if<sizeof...(DATATYPES) >= 1>) { } ... (various other constructor declarations here

我对模板元编程相当陌生,并且一直在研究其中的一些概念——然而,我遇到的这个特殊片段让我有些困惑

template<class TAG, typename... DATATYPES>
struct Message {

    Message (typename std::enable_if<sizeof...(DATATYPES) >= 1>) {
    }

    ... (various other constructor declarations here)

    std::tuple<DATATYPES...> m_data;
};
模板
结构消息{
消息(typename std::enable_if=1>){
}
…(此处有各种其他构造函数声明)
std::元组m_数据;
};
在阅读它时,我假设如果有一个或多个数据类型参数,它将启用默认构造函数,但在测试它之后,我得到的只是一个编译错误

我希望能得到任何帮助来帮助我理解这个片段,因为我知道enable_if应该做什么,但在这种情况下,我似乎无法理解实际发生的事情


编辑:我想这不是一个“如何实现这种特殊效果”的问题,而是一个“这段代码实际产生了什么”的问题,它是否符合我所理解的原作者的意图?“

std::enable\u如果
没有正确使用,如果后面没有
::type
<如果
本身是一个相当无用的
struct
类型,则启用

有条件地启用默认构造函数的正确方法:

template<class TAG, typename... DATATYPES>
struct Message {
private:
    struct dummy_type {};
public:
    template <typename T = std::tuple<DATATYPES...>>
    Message(
        typename std::enable_if<std::tuple_size<T>() >= 1, dummy_type>::type
        = dummy_type{}
    ) {}
    //...
};
模板
结构消息{
私人:
结构虚拟_类型{};
公众:
模板
信息(
typename std::enable_if=1,dummy_type>::type
=伪_类型{}
) {}
//...
};

std::enable\u如果
没有正确使用,如果后面没有
::键入
<如果
本身是一个相当无用的
struct
类型,则启用

有条件地启用默认构造函数的正确方法:

template<class TAG, typename... DATATYPES>
struct Message {
private:
    struct dummy_type {};
public:
    template <typename T = std::tuple<DATATYPES...>>
    Message(
        typename std::enable_if<std::tuple_size<T>() >= 1, dummy_type>::type
        = dummy_type{}
    ) {}
    //...
};
模板
结构消息{
私人:
结构虚拟_类型{};
公众:
模板
信息(
typename std::enable_if=1,dummy_type>::type
=伪_类型{}
) {}
//...
};

成员函数签名是类定义的一部分,需要在实例化类时解析。这意味着编译器也会在
时尝试启用_,如果条件未满,则会发现它没有嵌套的
类型
-硬错误

要使SFINAE工作,您需要将构造函数设置为模板,并在依赖于模板参数时启用
enable\u。例如,参见@acheplers的答案


OP中的代码所做的是一种奇怪的断言
数据类型
pack大小的方式,这将通过
static\u assert
更清楚地实现。或者,作者可能只是不知道如何正确执行SFINAE。

成员函数签名是类定义的一部分,需要在实例化类时进行解析。这意味着编译器也会在
时尝试启用_,如果条件未满,则会发现它没有嵌套的
类型-硬错误

要使SFINAE工作,您需要将构造函数设置为模板,并在依赖于模板参数时启用
enable\u。例如,参见@acheplers的答案


OP中的代码所做的是一种奇怪的断言
数据类型
pack大小的方式,这将通过
static\u assert
更清楚地实现。或者,也许作者只是不知道如何正确地进行SFINAE。

我没有时间发布完整的解决方案,但看看答案,同样的技术也可以应用到您的问题上,除了使用
IsVoid
,而不是使用
IsVoid
,您可以根据arg类型的数量定义一些内容。根据经验,如果在一个本身不是模板的函数(即类模板的成员不计算在内)中看到
enable\u if
,那就错了。我没有时间发布完整的解决方案,但看看答案,同样的技术也可以应用到您的问题上,除了不使用
IsVoid
,您可以根据arg类型的数量定义一些内容。根据经验,如果在一个本身不是模板的函数(即类模板的成员不计算在内)中看到
enable\u if
,则这是错误的。不幸的是,它将不起作用。构造函数本身需要是一个模板。如果enable_if条件的计算结果为true,那么它现在正在使用struct arg创建一个(无用的)构造函数吗?现在修复了它。不管有多少参数,原始代码都在用struct arg创建一个无用的构造函数。我明白了,谢谢。我猜原作者并不是有意这样做的。由于这是一个框架的片段,打算公开,我将尝试让作者知道。不幸的是,它不会起作用。构造函数本身需要是一个模板。如果enable_if条件的计算结果为true,那么它现在正在使用struct arg创建一个(无用的)构造函数吗?现在修复了它。不管有多少参数,原始代码都在用struct arg创建一个无用的构造函数。我明白了,谢谢。我猜原作者并不是有意这样做的。由于这是一个框架的片段,打算公开,我会尽量让作者知道。谢谢你的见解,非常感谢。我有一种直觉,认为代码没有达到预期目的,但我对概念缺乏坚定的理解,无法确定。感谢您的见解,非常感谢。我有一种直觉,认为代码没有达到预期的效果,但我对概念缺乏坚定的把握,无法确定。