c ++使用std :: enable_if有条件地将吸气剂添加到可变参数的变体模板中 [英] c++ Use std::enable_if to conditionally add getters to a variadic variant template

查看:102
本文介绍了c ++使用std :: enable_if有条件地将吸气剂添加到可变参数的变体模板中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的变体具有 int float bool 等中的任何一个作为模板参数的情况下,我尝试添加特殊化

I am trying to add specializations for the case where my variant has any of int, float, bool, and others as template arguments.

到目前为止,我的尝试是:

#include <iostream>
#include <variant>
#include <string>
#include <type_traits>

template<typename... Types>
struct variant : std::variant<Types...> {

    using std::variant<Types...>::variant;

    template<typename T>
    const T& get() const { return std::get<T>(*this); }

#define VARGET(X) typename std::enable_if<(std::is_same<Types, X>::value ||  ... ), X>::type get_##X() const { return get<X>(); }

    VARGET(int)
    VARGET(float)
    VARGET(double)
    VARGET(bool)
    using std_string = std::string;
    VARGET(std_string)
};

int main()
{

    variant<int, float, bool> var = 3;
    std::cout << var.get_int() << std::endl;

    variant<int, float, bool> var2 = 0.1f;
    std::cout << var2.get_float() << std::endl;

    return 0;
}

但是在gcc 9上会出现错误:

But on gcc 9 this gives the error:

error: failed requirement 'std::is_same<int, double>::value || std::is_same<float, double>::value || std::is_same<bool, double>::value'; 'enable_if' cannot be used to disable this declaration

这为什么让我感到困惑:

根据我对SFINAE的理解,当参数之一是指定的类型之一时,宏模板的计算结果为:(以int为例)

From my understanding of SFINAE, when one of the arguments is one of the specified types, the macro template evaluates to: (For the example of int)

std :: enable_if<(std :: is_same< Types,int> :: value || ...),int> :: type 的计算结果为 int

因此表达式变为 int get_int()const {std :: get< int>(* this)}

如果它不是指定的类型之一:

And if it is not one of the specified types:

std :: enable_if<(std :: is_same< Types,size_t> :: value || ...),size_t> :: type 的计算结果为空

因此表达式变为 get_size_t()const {std :: get< size_t>(* this)}

这是无效的语法,因为该函数没有返回类型,但是由于SFINAE的缘故,由于X的其他替换确实会产生有效的语法,因此该函数仍应编译.

This is invalid syntax because the function does not have a return type, but because of SFINAE this should still compile because of other substitutions of X do produce valid syntax.

我的代码有什么问题,有没有办法得到我想要的结果?

What is wrong with my code, and is there a way to get the result I desire?

谢谢.

推荐答案

我在尝试编译代码时收到的错误与您的错误不同,请参见在...中没有名为type的类型",因为SFINAE在这种情况下不适用.

The error I am receiving when trying to compile your code differs from yours, see on Compiler Explorer; I receive the error "no type named type in ..." which I would have expected, as SFINAE does not apply in this case.

SFINAE将应用于函数调用中.函数中没有任何东西可以替代,代码总是错误的/总是正确的,具体取决于结构的模板参数.

SFINAE would apply for instance in a function call if there is a substitution which whould cause a failure. Nothing were to be substituted in the function, the code is always wrong / always correct depending on the struct's template arguments.

在创建结构时,它要么总是格式错误,要么总是格式正确.您可以通过在函数中进行人工替换来解决此问题:

When creating the struct, it is either always malformed, or always well-formed. You might be able to work around this by imposing an artificial substitution in the function:

template <bool f=false>
std::enable_if_t<(std::is_same<Types, int>::value ||  ...  ||f ), int> get_int() const { return get<int>(); }

然后它应该可以正常编译.

Then it should compile fine.

替换发生在

  • 函数类型中使用的所有类型(包括返回类型和所有参数的类型)
  • 模板参数声明中使用的所有类型
  • 函数类型中使用的所有表达式
  • 模板参数声明中使用的所有表达式(自C ++ 11起)
  • 显式说明符中使用的所有表达式(自C ++ 20起)

事实上,代码被最佳压缩的原因是: std :: enable_if_t< false,int>func(){} 将始终无法编译.

The reason why the code is condensed best in the fact, that std::enable_if_t<false, int> func() {} will always fail to compile.

这篇关于c ++使用std :: enable_if有条件地将吸气剂添加到可变参数的变体模板中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆