【问题标题】:Check if valid template specialization检查是否有效的模板特化
【发布时间】:2014-02-21 15:23:18
【问题描述】:

我想检查是否可以使用给定的一组参数来专门化模板。以下是仅接受 1 个参数的模板版本:

#include <iostream>

template<template<typename...> class C, typename T>
struct is_valid_specialization {
    typedef struct { char _; } yes;
    typedef struct { yes _[2]; } no;

    template<template<typename...> class D, typename U>
    static yes test(D<U>*);
    template<template<typename...> class D, typename U>
    static no test(...);

    constexpr static bool value = (sizeof(test<C, T>(0)) == sizeof(yes));
};

template<typename T>
struct Test1 { };

template<typename T1, typename T2>
struct Test2 { };

template<typename...>
struct TestV { };

int main() {
    std::cout << "Test1<T>: " << is_valid_specialization<Test1, int>::value << std::endl;
    std::cout << "Test2<T>: " << is_valid_specialization<Test2, int>::value << std::endl;
    std::cout << "TestV<T>: " << is_valid_specialization<TestV, int>::value << std::endl;
}

这个does the job 用于模板只接受一个参数,但显然我也希望能够将它与多个参数一起使用,所以我尝试了这个:

template<template<typename...> class C, typename... T>
struct is_valid_specialization {
    typedef struct { char _; } yes;
    typedef struct { yes _[2]; } no;

    template<template<typename...> class D, typename... U>
    static yes test(D<U...>*);
    template<template<typename...> class D, typename... U>
    static no test(...);

    constexpr static bool value = (sizeof(test<C, T...>(0)) == sizeof(yes));
};

现在事情变得奇怪了,因为现在是value is always false

我有什么遗漏吗?这两个版本之间有什么完全不同的地方?还有其他方法可以实现吗?

编辑:
我已经为ClangGCC 提交了错误报告

【问题讨论】:

  • 当我不知道这样的事情有什么问题时,我会注释掉备用函数 (no test(...)) 并查看错误消息的内容。在这种情况下,编译器一直抱怨 D 的模板参数太多。打败我...
  • 顺便说一下,这些只测试参数是否匹配模板参数列表,而不是模板的完整实例化是否真的成功。后者是不可能的。

标签: c++ templates c++11 variadic-templates sfinae


【解决方案1】:

以下方法更简单有效:

template<template<typename...> class C, typename... T>
struct is_valid_specialization {
    typedef struct { char _; } yes;
    typedef struct { yes _[2]; } no;

    template<template<typename...> class D>
    static yes test(D<T...>*);
    template<template<typename...> class D>
    static no test(...);

    constexpr static bool value = (sizeof(test<C>(0)) == sizeof(yes));
};

Live example

【讨论】:

  • 我在你编辑之前看到“推论太复杂了”:) 我看不出有什么理由不可能。
  • @jrok 这就是我删除它的原因。我不知道究竟是什么导致了这个问题。
  • @TomKnapen 我很确定这是有原因的,在怀疑 GCC 和 Clang 之前,我总是怀疑我的代码 :)
  • originalmodified 代码都可以在 Visual C++ 上正常编译(当然,constexpr 关键字除外)。这些代码可以使用std::true_typestd::false_typestd::is_same进行简化。
  • @JosephGarvin 它检查参数的数量和种类,而不是它是否可以实例化。
【解决方案2】:

即使您明确指定了第一个 T... 参数,函数测试 (U...) 接受的模板参数的数量仍然未知。额外的 U... 模板参数可以从函数参数中推导出来。由于函数参数 (0) 无助于猜测 U... 的大小,所以第一个模板函数没有实例化。需要注意的是,模板参数 D 也可能采用任意数量的参数。编译器不应该做任何假设。

GCC 和 Clang 是对的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-05-24
    • 1970-01-01
    • 2021-09-04
    • 1970-01-01
    • 2019-08-19
    • 2014-11-08
    • 2018-10-21
    相关资源
    最近更新 更多