1

我试图在编译时使用可变参数模板来测试某些属性(type_trait),但似乎以下代码无法编译

template<typename test>
constexpr bool trait_test(){
    return test::value;
}

template<typename test, typename... Others>
constexpr bool trait_test(){
    return test::value&&trait_test<Others...>();
}

template<typename A, typename... Deriveds>
constexpr bool commonBaseClass{
    return trait_test<std::is_base_of<A,Deriveds>...>();
}

问题似乎是当“其他”的长度为 0 时,有 2 个可能的调用

trait_test<typename test>
trait_test<typename test, typename... Others={}>

并且编译器不知道要查看哪个。我当然想偷看第一个(并保留一切 constexpr)

4

2 回答 2

3

使您的代码编译的最小更改是将您的第二个test_trait重载替换为:

template<typename T0, typename T1, typename... Others>
constexpr bool trait_test(){
  return T0::value&&trait_test<T1, Others...>();
}

这意味着 1 个参数匹配第一个,2 个或更多匹配第二个。

于 2013-07-06T13:26:34.643 回答
2

确实这是模棱两可的。接受一个模板参数的函数模板并不比接受一个或多个模板参数的函数模板更专业,因为函数模板的部分排序是在函数参数上完成的 - 并且两个函数模板都有零个函数参数。

如果我可以建议另一种方法:

#include <type_traits>

template<typename... Ts>
struct all_of;

template<typename T>
struct all_of<T> : std::integral_constant<bool, T::value> { };

template<typename T, typename... Ts>
struct all_of<T, Ts...> : std::integral_constant<bool, 
    T::value && all_of<Ts...>::value> { };

template<typename A, typename... Deriveds>
constexpr bool commonBaseClass()
{
    return all_of<std::is_base_of<A, Deriveds>...>();
}

然后,您将使用commonBaseClass()这种方式:

struct X { };
struct Y : X { };
struct Z : X { };

int main()
{
    static_assert(commonBaseClass<X, Y, Z>(), "!");
}

这是一个活生生的例子

于 2013-07-06T13:08:56.050 回答