C++模板元编程实战

C++模板元编程实战练习题

基于《C++模板元编程入门与实战》的巩固练习,通过三个不同难度的题目,深入掌握编译期计算、类型萃取和模板特化的核心技术。

练习题概览

题目 难度 核心技能 预计完成时间
1. 通用向量点积计算 基础 函数模板、类模板、模板实例化 15分钟
2. 编译期快速幂算法 进阶 模板递归、constexpr、编译期计算 25分钟
3. 类型安全的容器适配器 挑战 类型萃取、SFINAE、模板特化 35分钟

环境要求

  • 编译器:支持C++17标准的g++或clang++
  • 编译命令:g++ -std=c++17 -o solution solution.cpp
  • 建议在Linux/macOS环境下测试,确保所有static_assert验证通过

题目一:通用向量点积计算(基础题)

题目描述

在数学和物理中,向量的点积(内积)是一个基本运算。你需要实现一个通用的点积计算模板,能够处理不同维度、不同类型的向量(如intfloatdouble等)。

具体要求

  1. 实现一个函数模板 dotProduct,接受两个相同长度的数组(向量),返回它们的点积结果。
  2. 实现一个类模板 Vector,封装固定长度的向量,并提供一个成员函数 dot 计算与另一个向量的点积。
  3. 确保代码类型安全:两个向量必须长度相同、元素类型可进行乘法运算。
  4. 编写测试代码,验证intfloat类型向量的点积计算。

解题思路提示

  1. 函数模板可以使用模板参数推导数组长度(通过std::size或模板非类型参数)。
  2. 类模板可以包含一个静态数组作为数据成员,长度作为模板非类型参数。
  3. 考虑使用auto作为返回类型,让编译器推导结果类型(防止溢出)。
  4. 使用static_assert确保两个向量长度相同。

解决方案代码

#include <iostream>
#include <type_traits>
#include <cstddef>

// ==================== 方案一:函数模板 ====================

/**
 * 通用点积计算函数模板
 * @tparam T 元素类型
 * @tparam N 向量长度(通过模板非类型参数指定)
 * @param a 第一个向量
 * @param b 第二个向量
 * @return 点积结果(类型为T)
 */
template<typename T, std::size_t N>
constexpr T dotProduct(const T (&a)[N], const T (&b)[N]) {
   
   
    T result = T(); // 零初始化
    for (std::size_t i = 0; i < N; ++i) {
   
   
        result += a[i] * b[i];
    }
    return result;
}

// 替代方案:使用指针和长度参数(更灵活)
template<typename T>
constexpr T dotProduct(const T* a, const T* b, std::size_t n) {
   
   
    T result = T();
    for (std::size_t i = 0; i < n; ++i) {
   
   
        result += a[i] * b[i];
    }
    return result;
}

// ==================== 方案二:类模板 ====================

/**
 * 通用向量类模板
 * @tparam T 元素类型
 * @tparam N 向量维度
 */
template<typename T, std::size_t N>
class Vector {
   
   
    T data[N]; // 静态数组存储向量元素
    
public:
    // 默认构造函数
    Vector() = default;
    
    // 初始化列表构造函数
    Vector(std::initializer_list<T> init) {
   
   
        std::size_t i = 0;
        for (const auto& val : init) {
   
   
            if (i < N) data[i++] = val;
        }
    }
    
    // 获取向量维度(静态版本,便于编译期使用)
    static constexpr std::size_t size() {
   
    return N; }
    
    // 下标访问(读写)
    T& operator[](std::size_t index) {
   
    return data[index]; }
    const T& operator[](std::size_t index) const {
   
    return data[index]; }
    
    /**
     * 计算与另一个向量的点积
     * @tparam U 另一个向量的元素类型(允许不同类型但可转换)
     * @param other 另一个向量
     * @return 点积结果(类型为decltype(data[0] * other[0]))
     */
    template<typename U>
    auto dot(const Vector<U, N>& other) const {
   
   
        // 编译期检查:确保两个向量长度相同
        static_assert(N == Vector<U, N>::size(), "Vectors must have same dimension");
        
        decltype(data[0] * other[0]) result = {
   
   }; // 自动推导结果类型
        for (std::size_t i = 0; i < N; ++i) {
   
   
            result += data[i] * other[i];
        }
        return result;
    }
    
    // 打印向量
    void print(const char* name = "") const {
   
   
        std::cout << name << " = [";
        for (std::size_t i = 0; i < N; ++i) {
   
   
            std::cout << data[i];
            if (i < N - 1) std::cout << ", ";
        }
        std::cout << "]" << std::endl;
    }
};

// ==================== 测试代码 ====================

int main() {
   
   
    std::cout << "=== 题目一:通用向量点积计算测试 ===\n\n";
    
    // 测试1:函数模板(数组版本)
    {
   
   
        constexpr int a1[] = {
   
   1, 2, 3};
        constexpr int b1[] = {
   
   4, 5, 6};
        int result1 = dotProduct(a1, b1);
        std::cout << "测试1 - 函数模板(int数组):\n";
        std::cout << "  dot([1,2,3], [4,5,6]) = " << result1 << std::endl;
        static_assert(sizeof(a1)/sizeof(a1[0]) == 3, "数组长度应为3");
    }
    
    // 测试2:函数模板(指针版本)
    {
   
   
        constexpr float a2[] = {
   
   1.5f, 2.5f};
        constexpr float b2[] = {
   
   2.0f, 3.0f};
        float result2 = dotProduct(a2, b2, 2);
        std::cout << "\n测试2 - 函数模板(float指针):\n";
        std::cout << "  dot([1.5,2.5], [2.0,3.0]) = " << result2 << std::endl;
    }
    
    // 测试3:类模板
    {
   
   
        Vector<int, 3> v1 = {
   
   1, 2, 3};
        Vector<int, 3> v2 = {
   
   4, 5, 6};
        auto result3 = v1.dot(v2);
        
        std::cout << "\n测试3 - 类模板(同类型):\n";
        v1.print("v1");
        v2.print("v2");
        std::cout << "  v1·v2 = " << result3 << std::endl;
    }
    
    // 测试4:混合类型(int与float)
    {
   
   
        Vector<int, 2> v3 = {
   
   2, 3};
        Vector<float
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

pchaoda

感谢支持~~~~~~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值