首页 > 解决方案 > 我可以使用 declval 构造未使用的返回吗?

问题描述

假设我有一个专门的模板化函数,所以我真的不关心基本实现。我可以做这样的事情:

template <typename T>
T dummy() {
    assert(false);
    return declval<T>();
}

当我尝试在中执行此操作时,出现链接错误:

函数中引用的未解析的外部符号char const && __cdecl std::declval<char const >(void)(??$declval@$$CBD@std@@YA$$QEBDXZ)char const __cdecl dummy<char const>()

同样,这个函数没有被调用,但我确实保存了一个指向它的指针。我可以return T{}改用它,并且可以编译,但即使没有默认构造函数,我也需要它来工作T。有没有办法解决这个问题?

标签: c++visual-studio-2017return-valuelinker-errorsdeclval

解决方案


您可以通过不提供函数模板的定义来解决此问题。使用

template <typename T>
T dummy();

template <>
int dummy() { std::cout << "template <> int dummy()"; return 42;}

int main()
{
    dummy<int>();
    dummy<double>();
    return 0;
}

您将收到链接器错误,因为dummy<double>();它不存在,但如果您将其注释掉,那么代码将编译,因为确实存在int. 这意味着您不必担心退货。


你可以使用

template <typename T>
T dummy() = delete;

而不是不提供定义,而不是得到链接器错误,你会得到一个“不错的”编译器错误,说明你正在尝试使用已删除的函数。这也允许您编写重载而不是特化,这是更可取的,因为在重载决议期间不考虑特化。在您的情况下这实际上是不可能的,因为您不采用任何参数,但如果您这样做,您应该考虑它。


推荐阅读