结合模板模板参数和可变参数模板的部分排序

时间:2018-07-25 20:16:10

标签: c++ g++ c++17 clang++

我对模板专业化以及可变参数模板和模板模板参数/参数有疑问。

以下小程序使用 Clang 6.0.1 GCC 8.1.1 (目标:x86_64-pc-linux-gnu)进行编译。

#include <iostream>

struct IndexSlot3 {
    static constexpr std::size_t size = 3;
};

template<typename T_, typename... IndexSlots_>
struct Tensor {
    Tensor() { std::cout << "Order N picked" << std::endl; }
};
template<typename T_, typename IndexSlot0_>
struct Tensor<T_, IndexSlot0_> {
    Tensor() { std::cout << "Order 1 picked" << std::endl; }
};
template<typename T_, typename IndexSlot0_, typename IndexSlot1_>
struct Tensor<T_, IndexSlot0_, IndexSlot1_> {
    Tensor() { std::cout << "Order 2 picked" << std::endl; }
};

int main(int argc, char** argv) {
    Tensor<int, IndexSlot3> t1;
    Tensor<int, IndexSlot3, IndexSlot3> t2;
    Tensor<int, IndexSlot3, IndexSlot3, IndexSlot3> t3;

    return 0;
}

编译命令:

clang++ -std=c++17 main.cpp -o main -Wall -Wpedantic
g++ -std=c++17 main.cpp -o main -Wall -Wpedantic

运行程序打印文件

Order 1 picked
Order 2 picked
Order N picked

与预期的一样,使用两个编译器。

但是,当我将以上内容扩展到以下程序时,Tensor也采用了定义存储的模板模板参数,在这三种情况下Clang都会选择主要模板,而GCC仍然会选择专业。

#include <iostream>

struct IndexSlot3 {
    static constexpr std::size_t size = 3;
};

template<typename T_, std::size_t... sizes>
struct CArrayStorage {
    using Type = T_*;
};
template<typename T_, std::size_t size0_>
struct CArrayStorage<T_, size0_> {
    using Type = T_[size0_];
};
template<typename T_, std::size_t size0_, std::size_t size1_>
struct CArrayStorage<T_, size0_, size1_> {
    using Type = T_[size0_][size1_];
};

template<typename T_,
        template<typename, std::size_t...> typename Storage_,
        typename... IndexSlots_>
struct Tensor {
    typename Storage_<T_, IndexSlots_::size...>::Type _storage;
    Tensor() { std::cout << "Order N picked" << std::endl; }
};
template<typename T_,
        template<typename, std::size_t> typename Storage_,
        typename IndexSlot0_>
struct Tensor<T_, Storage_, IndexSlot0_> {
    typename Storage_<T_, IndexSlot0_::size>::Type _storage;
    Tensor() { std::cout << "Order 1 picked" << std::endl; }
};
template<typename T_,
        template<typename, std::size_t, std::size_t> typename Storage_,
        typename IndexSlot0_, typename IndexSlot1_>
struct Tensor<T_, Storage_, IndexSlot0_, IndexSlot1_> {
    typename Storage_<T_, IndexSlot0_::size, IndexSlot1_::size>::Type _storage;
    Tensor() { std::cout << "Order 2 picked" << std::endl; }
};

int main(int argc, char** argv) {
    Tensor<int, CArrayStorage, IndexSlot3> t1;
    Tensor<int, CArrayStorage, IndexSlot3, IndexSlot3> t2;
    Tensor<int, CArrayStorage, IndexSlot3, IndexSlot3, IndexSlot3> t3;

    return 0;
}

使用Clang输出:

Order N picked
Order N picked
Order N picked

带有GCC的输出:

Order 1 picked
Order 2 picked
Order N picked

认为 GCC是正确的,因为专业化和主要匹配都很好,因此应选择专业化。但是我不确定模板参数的引入如何改变事情。

我应该针对Clang提交错误吗? 针对GCC? 反对两者? 我是否已经进入未定义行为的境界而没有意识到呢?

任何帮助将不胜感激。

[示例并非完全是最小的,但我想提供一些上下文,以便您可以理解我的工作。]

0 个答案:

没有答案
相关问题