概念检查器不会在 GCC 上编译,因为它'has no linkage'
concept checker doesn't compile on gcc because it 'has no linkage'
我基于这个问题创建了一个概念检查类,其目的是确保给定的类具有一个名为baseUnitConversionFactor
的静态成员函数。该类在msvc2013上编译并运行良好,但它不会在gcc 4.9.2上编译(使用-std=c++14),错误为:
错误:"{匿名}::UnitsTest_conceptChecker_Test::TestBody()::validUnit::baseUnitConversionFactor"不是类型"double(*)()"的有效模板参数,因为"static double{匿名}::UnitsTest_conceptChecker_Test::TestBody()::validUnit::baseUnitConversionFactor()"没有链接
static std::true_type test(tester<&U::baseUnitConversionFactor>*);
我真的不知道这意味着什么,我更熟悉视觉工作室中的写作模板(显然)——更宽容的环境。有人能帮我弄清楚我需要做什么来解决这个问题吗?
概念检查器类
template <typename T>
struct has_baseUnitConversionFactor
{
template<double(*)()> struct tester;
template<typename U>
static std::true_type test(tester<&U::baseUnitConversionFactor>*);
template<typename U>
static std::false_type test(...);
static const bool value = decltype(test<T>(0))::value;
};
我认为导致错误的测试
TEST_F(UnitsTest, conceptChecker)
{
struct validUnit
{
static inline double baseUnitConversionFactor() { return 0.0; }
typedef void unit_category;
typedef void base_unit_type;
};
EXPECT_TRUE(has_baseUnitConversionFactor<validUnit>::value);
}
在C++11和C++14中,指针/引用模板参数必须引用具有链接的实体(在C++03中,它们仅限于具有外部链接的实体)。局部类没有链接,它的成员函数也没有。
这一限制在C++17中被N4268删除,GCC主干声称已经实现了该论文,但显然没有实现链接部分。
回避此问题需要不使用&U::baseUnitConversionFactor
作为模板非类型参数。令人高兴的是,测试表达式T::baseUnitConversionFactor()
是否有效并准确返回double
的一种简单得多的方法是:
template <typename T, class=double>
struct has_baseUnitConversionFactor : std::false_type { };
template <typename T>
struct has_baseUnitConversionFactor<T, decltype(T::baseUnitConversionFactor())>
: std::true_type { };
这确实取决于表达式SFINAE(但是,原文也是如此),所以我不确定它是否适用于MSVC 2013。
要进行更全面的检查,您可能需要查看std::experimental::is_detected_convertible
。该cppreference页面有一个引用实现。
令人烦恼的是,这个问题似乎是由gtest使用匿名名称空间的方式引起的。将validUnit
声明移动到测试fixture(称为UnitsTest)中,并将EXPECT语句更改为使用fixture名称空间解决了这个问题。
更新的夹具
class UnitsTest : public ::testing::Test {
protected:
UnitsTest()
{
}
virtual ~UnitsTest()
{
}
virtual void SetUp()
{
}
virtual void TearDown()
{
}
struct validUnit
{
static inline double baseUnitConversionFactor() { return 0.0; }
typedef void unit_category;
typedef void base_unit_type;
};
};
更新的测试
TEST_F(UnitsTest, conceptChecker)
{
EXPECT_TRUE(has_baseUnitConversionFactor<UnitsTest::validUnit>::value);
}
- C++ Windows 驱动程序MSB3030无法复制该文件,因为它找不到
- 我可以在这里替换什么,因为我不能在 C# 中使用隐式变量的 lambda 函数?
- 程序无法启动,因为缺少 libmpc-3.dll
- 数组类型 int[n][n] 不可赋值,因为表达式必须具有常量值
- 在这个函数中是有缺陷的,因为取消引用 null 是无效的,所以我想更改代码
- 无法为 X.radio 创建中等可视化,因为找不到网络节点可视化 - Omnet++
- 在编译时,C++项目抛出错误 C2228,这是预期的,因为控件在运行时未达到该点
- C++ 程序不会因为内存而终止
- 为什么"fun(i)"被推导出为"fun<int&>"而不是"fun<int>",因为"i"是"int"的类型而不是参考?
- 将公共递归转换为尾递归,因为大型输入的堆栈溢出
- 无法使用 openssl 服务器,因为密码已过时...什么的...ERR_SSL_VERSION_OR_CIPHER_MISMATCH
- "this"关键字在C++中的实现限制,因为它与危险但功能示例有关
- 系统错误:程序无法启动,因为您的计算机中缺少MSVCP140D.DLL。尝试重新安装该程序以解决此问题
- 如何读取指针的值,因为这个指针是函数的返回?
- 无法加载 QML 插件:无法保护模块,因为它从未注册过
- 无法使用犰狳运行编译的 cpp 代码,因为 dyld:库未加载
- system() 无法运行我的程序,因为空间
- 我想知道为什么"std::unique_ptr<int> foo(新 int)"是合法的,因为"std::<int>unique_ptr"要求输入参数类型应该是"int"?
- 我必须构建我的项目 2 次,第一次失败,因为它无法打开库
- 概念检查器不会在 GCC 上编译,因为它'has no linkage'