C++ 如果使用constexpr bool测试不起作用,则启用

C++ 如果使用constexpr bool测试不起作用,则启用,c++,c++11,templates,constexpr,enable-if,C++,C++11,Templates,Constexpr,Enable If,我有一个数学函数,我希望能够接受一个double,或者一个double的数组/向量/容器,并且行为稍微不同 我试图使用SFINAE和type traits来选择正确的函数 下面是一个简单的例子: #include <iostream> #include <vector> #include <type_traits> template <typename T> constexpr bool Iscontainer() { if conste

我有一个数学函数,我希望能够接受一个double,或者一个double的数组/向量/容器,并且行为稍微不同

我试图使用SFINAE和type traits来选择正确的函数

下面是一个简单的例子:

#include <iostream>
#include <vector>
#include <type_traits>

template <typename T>
constexpr bool Iscontainer()
{
    if constexpr (std::is_class<T>::value && std::is_arithmetic<typename T::value_type>::value) {
        return true;
    }
    return false;
}

// Function 1 (double):
template <typename T>
typename std::enable_if<std::is_arithmetic<T>::value>::type g(T const & t)
{
    std::cout << "this is for a double" << t << std::endl;
}

// Function 2 (vec), version 1:
template <typename T>
typename std::enable_if<IsContainer<T>()>::type g(T const & t)
{
    std::cout << "this is for a container" << t[0] << std::endl;
}

int main()
{
    std::vector<double> v {1, 2};
    std::array<double, 2> a {1, 2};
    double d {0.1};

    g<>(v);
    g<>(a);
    g<>(d);  // error here
}
#包括
#包括
#包括
模板
constexpr bool Iscontainer()
{
如果constexpr(std::is_class::value&&std::is_算术::value){
返回true;
}
返回false;
}
//职能1(双重):
模板
typename std::enable_if::type g(T const&T)
{

std::cout似乎简单的重载完成了这项工作:

template <typename T>
void g(T const & t)
{
    std::cout << "this is for a double" << t << std::endl;
}

template <typename T>
void g(const std::vector<T>& t)
{
    std::cout << "this is for a vector" << t[0] << std::endl;
}

您的第二个版本使用SFINAE

// Function 2 (vec), version 2:
template <typename T>
typename std::enable_if<std::is_class<T>::value
                        && std::is_arithmetic<typename T::value_type>::value>::type
// SFINAE happens here for double                      ^^^^^^^^^^^^^
g(T const & t)
//函数2(vec),第2版:
模板
typename std::enable_if::type
//SFINAE在这里举行双人比赛^^^^^^^^^^^^^
g(施工及测试)

失败的原因很简单。您不调用SFINAE,当编译器尝试计算它看到的表达式时:

if constexpr (std::is_class<double>::value // this is fine it's false
   && std::is_arithmetic<typename double::value_type>::value // problem here!
)
或者,我建议使用别名

template <typename T>
using IsVector2 = std::conjunction<typename std::is_class<T>, std::is_arithmetic<typename T::value_type> >;

template <typename T>
typename std::enable_if<IsVector2<T>::value>::type g(T const & t)
{
    std::cout << "this is for a vector" << t[0] << std::endl;
}
模板
使用IsVector2=std::conjunction;
模板
typename std::enable_if::type g(T const&T)
{

std::cout-hmm,这是真的,如果我想让它也适用于std::数组呢?仍然对为什么它不起作用感兴趣work@dddd4那么添加另一个重载?我不知道的提供[]的类型呢与他们的数据接口?@dddd4:我还添加了使用代码解决问题的说明。因此,您的traits函数也不是您所期望的,您可能需要traits
具有_方括号(traits
运算符
或类似运算符。
// Function 2 (vec), version 2:
template <typename T>
typename std::enable_if<std::is_class<T>::value
                        && std::is_arithmetic<typename T::value_type>::value>::type
// SFINAE happens here for double                      ^^^^^^^^^^^^^
g(T const & t)
if constexpr (std::is_class<double>::value // this is fine it's false
   && std::is_arithmetic<typename double::value_type>::value // problem here!
)
#include <iostream>
#include <vector>
#include <type_traits>

template <typename T>
constexpr bool IsVector()
{
    if constexpr (std::is_class<T>::value) {
        if constexpr (std::is_arithmetic<typename T::value_type>::value) {
            return true;
        }
    }
    return false;
}

// Function 1 (double):
template <typename T>
typename std::enable_if<std::is_arithmetic<T>::value>::type g(T const & t)
{
    std::cout << "this is for a double" << t << std::endl;
}

// Function 2 (vec), version 1:
template <typename T>
typename std::enable_if<IsVector<T>()>::type g(T const & t)
{
    std::cout << "this is for a vector" << t[0] << std::endl;
}

int main()
{
    std::vector<double> v {1, 2};
    double d {0.1};

    g<>(v);
    g<>(d);  // error here
}
template <typename T>
using IsVector2 = std::conjunction<typename std::is_class<T>, std::is_arithmetic<typename T::value_type> >;

template <typename T>
typename std::enable_if<IsVector2<T>::value>::type g(T const & t)
{
    std::cout << "this is for a vector" << t[0] << std::endl;
}