C++ SFINAE没有';你不能使用constexpr函数吗?

C++ SFINAE没有';你不能使用constexpr函数吗?,c++,templates,c++11,constexpr,enable-if,C++,Templates,C++11,Constexpr,Enable If,为了支持可移植性,我想根据size\t是32位还是64位这一事实选择一个常量。 守则: using namespace std; namespace detail { template<enable_if<is_same<size_t, uint32_t>::value,void*>::type = nullptr> constexpr static const size_t defaultSizeHelper() { ret

为了支持可移植性,我想根据
size\t
是32位还是64位这一事实选择一个常量。 守则:

using namespace std;

namespace detail {
    template<enable_if<is_same<size_t, uint32_t>::value,void*>::type = nullptr>
    constexpr static const size_t defaultSizeHelper() {
        return ( (size_t) 1 << 30 ) / 2 * 5; //2,5 Gb
    }
    template<enable_if<is_same<size_t, uint64_t>::value,void*>::type = nullptr>
    constexpr size_t defaultSizeHelper() {
        return numeric_limits<size_t>::max() / 2;
    }
}

constexpr static size_t defaultSize = detail::defaultSizeHelper();
使用名称空间std;
名称空间详细信息{
模板
constexpr static const size\u t defaultSizeHelper(){
return((size_t)1背后的原理是,如果替换推导的模板参数导致代码格式错误,则该函数模板将从重载解析集中删除,而不是导致硬错误

在您的例子中,没有推导出的模板参数或替换模板参数,因此最终会出现编译错误

constexpr static size_t defaultSize = is_same<size_t, uint32_t>::value 
                                        ? (( (size_t) 1 << 30 ) / 2 * 5)
                                        : numeric_limits<size_t>::max() / 2;
constexpr static size\u t defaultSize=is\u same::value
(((大小)1问题
SFINAE代表替换失败不是错误

在实例化过程中,两个模板都不会失败,而是其中一个会在编译器查看后失败(因为它会看到enable_if不依赖于模板参数,并尝试直接展开它们)


解决方案 解决方案是使检查依赖于某个模板参数,这样编译器只能在可能的实例化时检查条件

在您的情况下,最简单的解决方案是简单地提供一个默认的模板参数,该参数是您想要检查的类型(
T

使用名称空间std;
名称空间详细信息{
模板
constexpr static const size\u t defaultSizeHelper(){

return((size_t)1哦,我忘了我可以混合元编程和普通代码!谢谢你提供了一个很好的解决方案!这个解决方案更好(一般来说,不是在这个特殊情况下),因为它不会引入额外的虚拟(嗯,一点也不)参数。还可以使用标记分派,这对于您的使用示例来说会更加优雅。
defaultSizeHelper(std::integral_constant{})
只是我前面评论的一个小补充,您的代码看起来像:使用标记分派时。
namespace detail {
    template<typename T, typename enable_if<is_same<T, uint32_t>::value,void*>::type = nullptr>
    constexpr static const T defaultSizeHelper(T) {
        return ( (size_t) 1 << 30 ) / 2 * 5; //2,5 Gb
    }
    template<typename T, typename enable_if<is_same<T, uint64_t>::value,void*>::type = nullptr>
    constexpr T defaultSizeHelper(T) {
        return numeric_limits<size_t>::max() / 2;
    }
}

constexpr static size_t defaultSize = detail::defaultSizeHelper(size_t{});
using namespace std;

namespace detail {
    template<class T = uint32_t, typename enable_if<is_same<size_t, T>::value,void*>::type = nullptr>
    constexpr static const size_t defaultSizeHelper() {
        return ( (size_t) 1 << 30 ) / 2 * 5; //2,5 Gb
    }

    template<class T = uint64_t, typename enable_if<is_same<size_t, T>::value,void*>::type = nullptr>
    constexpr size_t defaultSizeHelper() {
        return numeric_limits<size_t>::max() / 2;
    }
}

constexpr static size_t defaultSize = detail::defaultSizeHelper();