std::条件编译时分支评估

2022-01-20 00:00:00 conditional templates c++ c++11

编译:

template < class T, class Y, class ...Args >
struct isSame
{
    static constexpr bool value = std::conditional<
                                      sizeof...( Args ),
                                      typename std::conditional<
                                          std::is_same< T, Y >::value,
                                          isSame< Y, Args... >, // Error!
                                          std::false_type >::type,
                                      std::is_same< T, Y > >::type::value;
};

int main()
{
    qDebug() << isSame< double, int >::value;
    return EXIT_SUCCESS;
}

给我这个编译器错误:

error: wrong number of template arguments (1, should be 2 or more)

问题在于 isSame<double, int > 有一个空的 Args 参数包,所以 isSame<Y, Args... > 实际上变成了 isSame<;Y > 与签名不匹配.

The issue is that isSame< double, int > has an empty Args parameter pack, so isSame< Y, Args... > effectively becomes isSame< Y > which does not match the signature.

但我的问题是:为什么要评估那个分支?sizeof...( Args )false,因此不应评估内部 std:conditional.这不是运行时代码,编译器知道 sizeof..( Args ) 将永远 是 true 使用给定的模板类型.

But my question is: Why is that branch being evaluated at all? sizeof...( Args ) is false, so the inner std:conditional should not be evaluated. This isn't a runtime piece of code, the compiler knows that sizeof..( Args ) will never be true with the given template types.

如果你很好奇,它应该是 std::is_same 的可变参数版本,而不是它的工作原理......

If you're curious, it's supposed to be a variadic version of std::is_same, not that it works...

推荐答案

你有一个错误,因为在用作模板参数时类型必须正确.
您可以使用模板专业化来解决您的问题,例如:

You have an error because the type has to be correct when used as template parameter.
You may use template specialization to solve your issue, something like:

#include <type_traits>

template <typename ... Ts> struct are_same;

template <> struct are_same<> : std::true_type {};
template <typename T> struct are_same<T> : std::true_type {};

template <typename T1, typename T2, typename... Ts>
struct are_same<T1, T2, Ts...> :
    std::conditional<
        std::is_same<T1, T2>::value,
        are_same<T2, Ts...>,
        std::false_type
    >::type
{};

static_assert(are_same<char, char, char>::value, "all type should be identical");
static_assert(!are_same<char, char, int>::value, "all type should not be identical");

相关文章