如果从未在未评估的上下文之外调用模板,是否返回 declval UB?
Is returning declval UB if the template is never called outside of unevaluated context?
我正在编写一些元函数,并且我想到使用 C++17 的 if constexpr 结合推导的 return 类型来编写它们。这是一个例子:
#include <tuple>
#include <type_traits>
#include <string>
template<typename TupleType, std::size_t I = 0, typename... ReturnData>
constexpr auto filterImpl()
{
if constexpr (I < std::tuple_size_v<TupleType>)
{
using Type = std::tuple_element_t<I, TupleType>;
if constexpr (std::is_arithmetic_v<Type>)
return filterImpl<TupleType, I + 1, ReturnData..., Type>();
else
return filterImpl<TupleType, I + 1, ReturnData...>();
}
else
return std::declval<std::tuple<ReturnData...>>();
}
template<typename Tuple>
using FilterTuple = decltype(filterImpl<Tuple>());
//std::tuple<int, float>
using MyTuple = FilterTuple<std::tuple<int, std::string, float, int*>>;
int main(int argc, char* argv[])
{
MyTuple t{ 3, 5.f };
return 0;
}
当然,您可以使用更简单的模式来解决这个问题,但这只是我想要做的事情的一个基本示例。
这段代码可以在 msvc 上编译,但不能在 onlinegdb 上编译。
哪一个是对的?
以这种方式使用 declval 是否被授权?
我应该像那样写我的元函数,还是应该回到模板 类?
(我认为,如果有办法做到这一点,更复杂的元函数最终可能更容易以这种方式阅读)
一个mcve:
#include <utility>
template<bool b>
constexpr auto evil()
{
if constexpr (b)
return 0;
else
return std::declval<int>();
}
template<bool b>
using Test = decltype(evil<b>());
int main()
{
Test<false> t{};
}
因为你必须实例化函数模板来确定它的return类型,所以有一个函数odr-uses std::declval<…>
,所以程序格式错误。 MSVC 接受它是错误的(没有警告),尽管可以争辩说这条规则不应该需要诊断来允许明显的实施策略,即未能提供 definition对于std::declval
.
我正在编写一些元函数,并且我想到使用 C++17 的 if constexpr 结合推导的 return 类型来编写它们。这是一个例子:
#include <tuple>
#include <type_traits>
#include <string>
template<typename TupleType, std::size_t I = 0, typename... ReturnData>
constexpr auto filterImpl()
{
if constexpr (I < std::tuple_size_v<TupleType>)
{
using Type = std::tuple_element_t<I, TupleType>;
if constexpr (std::is_arithmetic_v<Type>)
return filterImpl<TupleType, I + 1, ReturnData..., Type>();
else
return filterImpl<TupleType, I + 1, ReturnData...>();
}
else
return std::declval<std::tuple<ReturnData...>>();
}
template<typename Tuple>
using FilterTuple = decltype(filterImpl<Tuple>());
//std::tuple<int, float>
using MyTuple = FilterTuple<std::tuple<int, std::string, float, int*>>;
int main(int argc, char* argv[])
{
MyTuple t{ 3, 5.f };
return 0;
}
当然,您可以使用更简单的模式来解决这个问题,但这只是我想要做的事情的一个基本示例。
这段代码可以在 msvc 上编译,但不能在 onlinegdb 上编译。 哪一个是对的? 以这种方式使用 declval 是否被授权? 我应该像那样写我的元函数,还是应该回到模板 类?
(我认为,如果有办法做到这一点,更复杂的元函数最终可能更容易以这种方式阅读)
一个mcve:
#include <utility>
template<bool b>
constexpr auto evil()
{
if constexpr (b)
return 0;
else
return std::declval<int>();
}
template<bool b>
using Test = decltype(evil<b>());
int main()
{
Test<false> t{};
}
因为你必须实例化函数模板来确定它的return类型,所以有一个函数odr-uses std::declval<…>
,所以程序格式错误。 MSVC 接受它是错误的(没有警告),尽管可以争辩说这条规则不应该需要诊断来允许明显的实施策略,即未能提供 definition对于std::declval
.