使用SFINAE检测constexpr [英] Detecting constexpr with SFINAE

查看:157
本文介绍了使用SFINAE检测constexpr的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在努力升级一些C ++代码以利用C ++ 11中的新功能。我有一个trait类与几个函数返回基本类型,这在大多数时候,但不总是,返回一个常量表达式。我想根据函数是否 constexpr 做不同的事情。我想出了以下方法:

  template< typename Trait> 
struct test
{
template< int Value = Trait :: f()>
static std :: true_type do_call(int){return std :: true_type(); }

static std :: false_type do_call(...){return std :: false_type(); }

static bool call(){return do_call(0); }
};

struct trait
{
static int f(){return 15; }
};

struct ctrait
{
static constexpr int f(){return 20; }
};

int main()
{
std :: cout< regular:<< test< trait> :: call()<< std :: endl;
std :: cout<< constexpr:< test< ctrait> :: call()<< std :: endl;
}

额外的 int / ... 参数是这样,如果两个函数在 SFINAE 后可用,第一个通过重载分辨率来选择。

使用 Clang 3.2 编译和运行此操作显示:

  regular:0 
constexpr:1

所以这看起来工作,但我想知道代码是否合法C ++ 11。

解决方案


p> 注意我在此处打开了一个问题,说明OPs代码是否实际有效。以下重写的示例将适用于任何情况。








但我想知道代码是否合法C ++ 11


这是,虽然可以考虑默认的模板参数有点不寻常。我个人喜欢下面的风格更好,这是类似于你(读:我)写一个trait到检查函数的存在< a>,只需使用非类型模板参数并省略 decltype

  #include< type_traits> 

命名空间详细信息{
template< int> struct sfinae_true:std :: true_type {};
template< class T>
sfinae_true<(T :: f(),0)> check(int);
template< class>
std :: false_type check(...);
} // detail ::

template< class T>
struct has_constexpr_f:decltype(detail :: check< T>(0)){};

Live example。 a>






说明时间〜



,因为默认模板参数的实例化点是其函数模板的实例化点,在你的情况下,在 main



§14.6.4.1[temp.point] p2


如果一个函数模板[...]被调用,使用该函数模板的默认参数定义[...] ,默认参数的实例化点是函数模板[...]的实例化点。


它只是通常的SFINAE规则。






†至少我认为,这不是完全标准。


I'm working on upgrading some C++ code to take advantage of the new functionality in C++11. I have a trait class with a few functions returning fundamental types which would most of the time, but not always, return a constant expression. I would like to do different things based on whether the function is constexpr or not. I came up with the following approach:

template<typename Trait>
struct test
{
    template<int Value = Trait::f()>
    static std::true_type do_call(int){ return std::true_type(); }

    static std::false_type do_call(...){ return std::false_type(); }

    static bool call(){ return do_call(0); }
};

struct trait
{
    static int f(){ return 15; }
};

struct ctrait
{
    static constexpr int f(){ return 20; }
};

int main()
{
   std::cout << "regular: " << test<trait>::call() << std::endl;
   std::cout << "constexpr: " << test<ctrait>::call() << std::endl;
}

The extra int/... parameter is there so that if both functions are available after SFINAE, the first one gets chosen by overloading resolution.

Compiling and running this with Clang 3.2 shows:

regular: 0
constexpr: 1

So this appears to work, but I would like to know if the code is legal C++11. Specially since it's my understanding that the rules for SFINAE have changed.

解决方案

NOTE: I opened a question here about whether OPs code is actually valid. My rewritten example below will work in any case.


but I would like to know if the code is legal C++11

It is, although the default template argument may be considered a bit unusual. I personally like the following style better, which is similar to how you (read: I) write a trait to check for a function's existence, just using a non-type template parameter and leaving out the decltype:

#include <type_traits>

namespace detail{
template<int> struct sfinae_true : std::true_type{};
template<class T>
sfinae_true<(T::f(), 0)> check(int);
template<class>
std::false_type check(...);
} // detail::

template<class T>
struct has_constexpr_f : decltype(detail::check<T>(0)){};

Live example.


Explanation time~

Your original code works because a default template argument's point of instantiation is the point of instantiation of its function template, meaning, in your case, in main, so it can't be substituted earlier than that.

§14.6.4.1 [temp.point] p2

If a function template [...] is called in a way which uses the definition of a default argument of that function template [...], the point of instantiation of the default argument is the point of instantiation of the function template [...].

After that, it's just usual SFINAE rules.


† Atleast I think so, it's not entirely clear in the standard.

这篇关于使用SFINAE检测constexpr的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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