c++ - 当返回值是class或class<class>或class<class, class>等时如何使用enable_if?

标签 c++ enable-if template-templates

以下简化的类在从 get() 返回值时执行不同的操作,具体取决于该类是被赋予 double 值还是数组作为模板参数:

#include "array"
#include "type_traits"

template<class T> class C
{
public:
    T get(const int arg) {
        return this->impl<T>(arg);
    }

private:
    template<class Out_T> typename std::enable_if<
        std::is_same<Out_T, double>::value,
        Out_T
    >::type impl(const int arg) { return 1; }

    template<class Out_T> typename std::enable_if<
        std::is_same<Out_T, std::array<double, 3>>::value,
        Out_T
    >::type impl(const int arg) { return {1, 2, 3}; }
};

int main(int argc, char* argv[])
{
    C<double> c1;
    C<std::array<double, 3>> c2;

    return c1.get(0) < c2.get(0)[1];
}

我应该如何编写 impl 的数组版本,以便支持数组中的任意数量的项?来自 g++-4.8.2 和 clang++-3.5 的错误没有帮助。我认为最接近的是:

    template<
        template<class...> class Out_T,
        class... Args
    > typename std::enable_if<
        std::is_same<Out_T<Args...>, std::array<Args...>>::value,
        Out_T<Args...>
    >::type impl(const int arg) { return {1, 2, 3}; }

但 clang 仍然报错:

testi.cpp:8:20: error: no matching member function for call to 'impl'
                return this->impl<T>(arg);
                       ~~~~~~^~~~~~~
testi.cpp:31:28: note: in instantiation of member function 'C<std::__1::array<double, 3> >::get' requested
      here
        return c1.get(0) < c2.get(0)[1];
                              ^
testi.cpp:13:7: note: candidate template ignored: disabled by 'enable_if' [with Out_T =
      std::__1::array<double, 3>]
                std::is_same<Out_T, double>::value,
                ^
testi.cpp:23:14: note: candidate template ignored: invalid explicitly-specified argument for template
      parameter 'Out_T'
        >::type impl(const int arg) { return {1, 2, 3}; }
                ^

最佳答案

更改模板声明:

template<
    template<class...> class Out_T,
    class... Args
>

template<
    class Out_T
>

并将返回类型更改为:

typename std::enable_if<
    detail::is_standard_array<Out_T>::value,
    Out_T
>::type

其中 is_standard_array 是一个辅助模板,它返回一个 bool 值来确定类型是否为 std::array:

namespace detail
{
    template<class T>
    struct is_standard_array : std::false_type { };

    template<class T, std::size_t N>
    struct is_standard_array<std::array<T, N>> : std::true_type { };
}

问题是 Args.... 参数包没有提供给 impl() 的函数调用,因此编译器将其排除在外重载。您还可以为类 std::array 专门化 C 并适本地修改 get()

关于c++ - 当返回值是class或class<class>或class<class, class>等时如何使用enable_if?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24786077/

相关文章:

c++ - 为什么模板参数中的 enable_if_t 提示重新定义?

c++ - 是否可以完美转发模板模板参数

c++ - 内部模板类作为模板模板参数

c++ - SizeOfImage 成员导致程序崩溃

c++ - 有没有一种方法可以使用 SFINAE 来确定对模板函数的调用是否会由于提供的类型而失败?

c++ - 为什么 std::sort 假定 std::vector< std::vector<int>> 默认为 std::vector,从而产生错误的结果?

c++ - enable_if 用于没有返回类型的函数

c++ - 如何将模板内部的模板作为模板模板参数传递给另一个模板?

c++ - 是否有在 Windows 上分发 C/C++ 开发包(无源)的首选规范方法?

c++ - glibc(或 libc6)库版本