c++ - 如果模板从未在未评估的上下文之外被调用,是否返回 declval UB?

标签 c++ c++17 metaprogramming

我正在编写一些元函数,并且我有想法使用 C++17 的 if constexpr 结合推导的返回类型来编写它们。这是一个例子:

#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{};
}

最佳答案

因为你必须实例化 确定其返回类型的函数模板,有一个函数是 ODR 用途 std::declval<…> ,所以程序格式错误。 MSVC 错误地接受了它(没有警告),尽管可以说这条规则不应该需要诊断来允许明显的实现策略,即未能提供 定义 std::declval .

关于c++ - 如果模板从未在未评估的上下文之外被调用,是否返回 declval UB?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68068589/

相关文章:

c++ - lower_bound() 算法/STL 使用前提条件

c++ - 如何从函数类型自动推断返回类型?

c++ - 如何在 Boost.MPL 中使用嵌套元函数?

c++ - 是否有一个 c++(MFC) 数据库对象可以在一条指令中执行多个 SQL 语句(如在脚本中)?

c++ - boost 异步服务器缓冲区错误

c++ - 关于将指向 C++17 标准变体的指针传递给需要 const 引用的函数的不一致行为

c++ - TypeA 和 TypeB 是同一主类型的别名,如何在 C++ 模板中将它们推导为不同类型?

c++ - 有没有办法在加载 dll 时调试发布版本?

java - 为什么在 C++ 中使用 this->ObjectName 而不是 this.ObjectName

c++ - 类数据成员中可以使用模板参数推导吗?