参数包和constexpr静态

时间:2018-06-04 14:33:42

标签: c++11 variadic-templates

使用带有右值引用和const类成员数据的参数包扩展会导致Clang 5和6以及GCC 4.8.5和5.3出现链接错误。我第一次遇到与std::make_shared具有相同签名的函数的问题,但已将其简化为以下测试用例,显示了我希望工作的6种不同方式。

#include <utility>

constexpr int global_value = 3;

struct Foo {
    static constexpr int value = 3;
};

struct Bar {
    static const int value = 3;
};

using Baz = std::integral_constant<int, 3>;

template<class... Args>
int* make(Args&&... args)
{
    return new int(std::forward<Args>(args)...);
}

template<class... Args>
int* make_nofwd(Args&&... args)
{
    return new int(args...);
}

template<class... Args>
int* make_norvalue(Args... args)
{
    return new int(args...);
}

int main(int, char** )
{
#if ATTEMPT == 0
    int* v = make(Foo::value); // FAIL
#elif ATTEMPT == 1
    int* v = make_nofwd(Foo::value); // FAIL
#elif ATTEMPT == 2
    int* v = make_norvalue(Foo::value); // OK
#elif ATTEMPT == 3
    int* v = make(global_value); // OK
#elif ATTEMPT == 4
    int* v = make(Bar::value); // OK
#elif ATTEMPT == 5
    int* v = make(Baz::value); // OK
#endif
    return (*v == 3 ? 0 : 1);
}

运行每次尝试都表明,当作为rvalues传递时,结构的常量和constexpr数据不会被插入。

$ for i in {0..4}; do echo "=== Attempt $i ==="; g++ derp.cc -Wall -Wextra -std=c++11 -D ATTEMPT=$i -o derp.exe && ./derp.exe && echo "SUCCESS" ; done
=== Attempt 0 ===
/tmp/ccC5TyiZ.o: In function `main':
derp.cc:(.text+0x10): undefined reference to `Foo::value'
collect2: error: ld returned 1 exit status
=== Attempt 1 ===
/tmp/ccCwlV85.o: In function `main':
derp.cc:(.text+0x10): undefined reference to `Foo::value'
collect2: error: ld returned 1 exit status
=== Attempt 2 ===
SUCCESS
=== Attempt 3 ===
SUCCESS
=== Attempt 4 ===
/tmp/ccnfzmHk.o: In function `main':
derp.cc:(.text+0x10): undefined reference to `Bar::value'
collect2: error: ld returned 1 exit status
=== Attempt 5 ===
SUCCESS

并且,我刚刚发现任何优化运行都会神奇地修复它:

for i in {0..4}; do echo "=== Attempt $i ==="; $CXX derp.cc -Wall -Wextra -std=c++11 -D ATTEMPT=$i -O2 -o derp.exe && ./derp.exe && echo "SUCCESS" ; done;
=== Attempt 0 ===
SUCCESS
=== Attempt 1 ===
SUCCESS
=== Attempt 2 ===
SUCCESS
=== Attempt 3 ===
SUCCESS
=== Attempt 4 ===
SUCCESS
=== Attempt 5 ===
SUCCESS

我在某种程度上使用未指明的行为吗?为什么Args&&没有通过值传递int

0 个答案:

没有答案