为什么Visual Studio不允许我在enable_if中使用Templatized,constexpr函数?

Jon*_*Mee 8 c++ templates constexpr c++11 visual-studio-2015

所以我把它归结为最小的,完整的,可验证的例子,看起来Visual Studio 2015似乎不允许我使用一个模板化的constexpr函数enable_if.

例如:

template <typename T>
constexpr bool condition() { return sizeof(T) > 1; }
Run Code Online (Sandbox Code Playgroud)

给我错误:

错误C2995 :: enable_if<_Test,T>::type test(void)功能模板已经定义

当我尝试在替换中使用它时,失败不是像这样的错误编译:

template <typename T>
enable_if_t<condition<T>()> test() { cout << "true\n"; }

template <typename T>
enable_if_t<!condition<T>()> test() { cout << "false\n"; }
Run Code Online (Sandbox Code Playgroud)

这在gcc中运行良好:http ://ideone.com/m9LDdS
如果我删除了它的模板化,它在Visual Studio 2015中工作正常condition.我相信constexpr函数是在中引入的,为什么Visual Studio 2015不支持这个?这是一个错误吗?

Sim*_*mer 6

问题似乎是MSVC14/VS2015无法正确解析SFINAE表达式并结合constexpr函数的返回值作为模板参数.

作为一种变通方法,您可以将constexpr的返回值赋给结构的"static const"成员,并将此成员用作模板参数.

#include <type_traits>
#include <iostream>

using std::enable_if_t;
using std::cout;

template <typename T>
constexpr bool condition() { return sizeof(T) > 1; }

template <typename T>
struct condition_ { static const bool value = condition<T>();};

template <typename T>
enable_if_t<condition_<T>::value> test() { cout << "true\n"; }
template <typename T>
enable_if_t<!condition_<T>::value> test() { cout << "false\n"; }

int main() {
    test<int>();
    test<bool>();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

http://rextester.com/VVNHB62598


您还在评论中提到您的实际问题出现在另一个案例中而不是您的MCVE(如何初始化div_t对象?)

对于这种情况,解决方法可能如下所示:

#include <type_traits>
#include <cstdlib>
#include <utility>


template <typename T>
using divtype = decltype(std::div(std::declval<T>(), std::declval<T>()));


template <typename T>
struct condition
{
    static const bool value = divtype<T>{ 1, 0 }.quot != 0;
};


template <typename T>
std::enable_if_t<condition<T>::value, divtype<T>> make_div(const T quot, const T rem) { return{ quot, rem }; }

template <typename T>
std::enable_if_t<!condition<T>::value, divtype<T>> make_div(const T quot, const T rem) { return{ rem, quot }; }

int main() {

    make_div<int>(1, 2);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

http://rextester.com/ULDFM22040


根据Visual Studio C++团队的博客文章 VS2015还没有(完全)支持Expression SFINAE.

[1]我们计划在2015 RTM之后立即开始在编译器中实现Expression SFINAE,并且我们计划在2015年更新中提供它,支持生产使用.(但不一定是2015年更新1.可能需要更长时间.)