我们有很大的计算几何库。它的内核有问题。我们有定义标量 taits 和自由函数形式的辅助访问器,可以简单地编写cg::epsilon<T>()而不是cg::scalar_traits<T>::epsilon. 但问题是,在 vs2008 和 vs2010 下,它有时会争论它无法推断出Tin 的模板参数cg::epsilon<T>。在 LWS 的其他编译器上工作正常。
重现的简化版本:
namespace cg
{
template<class S>
S epsilon();
template<>
double epsilon<double>() {return 1;}
template<>
float epsilon<float>() {return 1;}
template<class S>
bool eq(S a, S b, S eps = cg::epsilon<S>())
{
return true;
}
}
int main(int argc, char* argv[])
{
cg::eq(0.0, 0.0);
cg::eq(0.0f, 0.0f);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
是否有一些解决方法可以使访问器正常工作?
PS:我们使用cg::scalar_traits<S>::epsilon(), 这有助于发生错误,但是太冗长了
研究:甚至宣称
template<class S>
bool eq(S a, S b, S …Run Code Online (Sandbox Code Playgroud) Visual C++ 2012.代码.我认为它应该编译; 编者恭敬地不同意.我把我的责备缩小到:
struct B { };
void foo(B* b, signed int si) { } // Overload 1
void foo(B const* b, unsigned int ui) { } // Overload 2
int main()
{
B b;
unsigned int ui;
foo(&b, ui);
}
Run Code Online (Sandbox Code Playgroud)
所以我们有两个重载决策候选者.对于第一个重载,第一个参数完全匹配,第二个参数需要整数转换(unsigned to signed).对于第二个重载,第二个参数完全匹配,第一个参数需要cv-adjustment(因为&b是指向非const的指针).
现在,似乎这应该是完全明确的.对于Overload 1,第一个参数是标准关于重载决策的部分定义的"精确匹配",但第二个参数是"转换".对于Overload 2,两个参数都是"Exact Matches"(资格转换与身份相同).因此(我显然不完美的推理),应该选择Overload 2,没有歧义.但是:
a.cpp(12): error C2666: 'foo' : 2 overloads have similar conversions
a.cpp(6): could be 'void foo(const B *,unsigned int)'
a.cpp(5): or 'void foo(B *,int)'
while trying to match the …Run Code Online (Sandbox Code Playgroud) 使用 MSVC 19.11 编译以下代码会产生输出
With 32: 0 99 2 With 64: 0 1 2使用 32 位编译器,并在
With 32: 0 1 2 With 64: 0 99 2使用 64 位编译器。
问题是单个元素初始值设定项列表的类型恰好是size_t。这是一个编译器错误(到目前为止我还没有发现它在任何地方报告过),而不是标准不明确的情况(clang 和 gcc 都没有这个问题)?
#include <cstdint>
#include <vector>
#include <iostream>
int main() {
using T = std::uint16_t;
// fixed with uint32 / uint64 on 32 / 64 bit compilers, respectively,
// but not with int32_t / int64_t
{
std::vector<T> s0;
// std::vector<T> s1{ 99u }; // OK
// …Run Code Online (Sandbox Code Playgroud) Clang 8.0.0 和 GCC 9.1.0 似乎不同意这是否是有效代码。
struct Foo {
Foo([[maybe_unused]] int x) {}
};
int main() {}
Run Code Online (Sandbox Code Playgroud)
Clang 不产生警告(即使使用-Wall -Wextra -Wpedantic),但 GCC 产生此错误:
test.cpp:2:7: error: expected unqualified-id before '[' token
2 | Foo([[maybe_unused]] int x) {}
| ^
test.cpp:2:7: error: expected ')' before '[' token
2 | Foo([[maybe_unused]] int x) {}
| ~^
| )
Run Code Online (Sandbox Code Playgroud)
那么哪个编译器有错误?
下面的代码
#include <cstdint>
#include <array>
#include <utility>
std::size_t constexpr num = 5;
using Doubles = std::array<double, num>;
struct meow {
template<typename V>
static constexpr V value(V v, std::size_t)
{
return v;
}
template<typename V, std::size_t... Indices>
static constexpr auto make(V v, std::index_sequence<Indices...>) -> std::array<V, sizeof...(Indices)>
{
return {{value(v, Indices)...}};
}
Doubles doubles = make(3.1415926535897932384626433, std::make_index_sequence<num>());
};
int main()
{
meow m;
return m.doubles.size();
}
Run Code Online (Sandbox Code Playgroud)
由 GCC 以合理的方式编译,但 clang 尝试调用meow::make<double,0,1,2,3,4>而不生成实现:
https://godbolt.org/z/9Mv67GeYW
到底是怎么回事?我是否进入了IFNDR领域?
我有一个包装数组的类。它继承自一个抽象基类,virtual constexpr为函数调用运算符定义一种方法。在子类中,我重写所述方法并访问内部数组:
#include <cstddef>\n#include <array>\n#include <initializer_list>\n\ntemplate <typename T, std::size_t N>\nclass ContainerBase {\npublic:\n virtual constexpr const T& operator()(std::size_t i) const = 0;\n};\n\ntemplate <typename T, std::size_t N>\nclass Container : public ContainerBase<T, N> {\npublic:\n constexpr Container(std::initializer_list<T> data) {\n std::copy(data.begin(), data.end(), _items.begin());\n }\n constexpr const T& operator()(std::size_t i) const override {\n return _items[i];\n }\nprivate:\n std::array<T, N> _items;\n};\n\nint main () {\n constexpr Container<int, 3> C = {2, -91, 7};\n constexpr int F = C(1);\n\n static_assert(F == -91);\n}\nRun Code Online (Sandbox Code Playgroud)\n这是Godbolt 链接。 …
我有以下 C++ 代码:
template<typename T>
class Foo;
template<typename T, typename U>
Foo<T> operator+(Foo<T> lhs, const Foo<U>& rhs);
template<typename T>
class Foo {
template<typename>
friend class Foo;
T inner;
public:
Foo(T i) : inner(i) {}
template<typename U>
friend Foo<T> operator+(Foo<T> lhs, const Foo<U>& rhs) {
lhs.inner += rhs.inner;
return lhs;
}
};
int main() {
Foo<int> a = 4;
Foo<unsigned> b = 5;
Foo<int> c = a + b;
}
Run Code Online (Sandbox Code Playgroud)
它可以使用 GCC 和 clang 正常编译,但在 MSVC v19.37 和 Visual Studio …
我有以下代码:
struct S {
// conditional noexcept specification which depends on noexceptness of foo()
void bar() noexcept(noexcept(foo()));
// conditional noexcept specification (true)
void foo() noexcept(true);
};
Run Code Online (Sandbox Code Playgroud)
Clang 拒绝此代码,但 GCC 允许它(https://godbolt.org/z/nxqa5Tr1x):
<source>:2:34: error: exception specification is not available until end of class definition
2 | void bar() noexcept(noexcept(foo()));
|
Run Code Online (Sandbox Code Playgroud)
替换noexcept(true)为noexcept两个编译器都允许
noexcept(true)失败但是noexcept成功?注意:这个例子显然是最小的。我的实际用例是,我有一个clear()成员函数,仅在自定义容器中为noexceptif clear_impl()is 。noexcept
#include <vector>
std::vector<int>::iterator foo();
void bar(void*) {}
int main()
{
void* p;
while (foo() != foo() && (p = 0, true))
{
bar(p);
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
结果有误:
c:\ users\jessepepper\source\repos\testcode\consoleapplication1\consoleapplication1.cpp(15):错误C4703:使用了未初始化的本地指针变量'p'
函数签名清楚地表明它应该返回一个Bool,为什么函数返回96?更重要的是,编译器认为96实际上是Bool.这是一个错误吗?
> isLeapYear year =\
| (modBy 4 year == 0) && (modBy 100 year /= 0) || (modBy 400 year == 0)
<function> : Int -> Bool
> isLeapYear 1996
96 : Bool
Run Code Online (Sandbox Code Playgroud)
它似乎有时工作:
> isLeapYear 2000
True : Bool
> isLeapYear 1800
False : Bool
Run Code Online (Sandbox Code Playgroud) compiler-bug ×10
c++ ×9
visual-c++ ×4
clang ×2
templates ×2
boolean ×1
c++11 ×1
c++14 ×1
c++20 ×1
constexpr ×1
elm ×1
noexcept ×1
overloading ×1